agentirc-cli 8.5.0__tar.gz → 8.7.0__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 (478) hide show
  1. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/CHANGELOG.md +29 -0
  2. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/PKG-INFO +2 -1
  3. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/bots/bot.py +24 -13
  4. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/bots/bot_manager.py +53 -24
  5. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/bots/http_listener.py +35 -1
  6. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/acp/agent_runner.py +53 -11
  7. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/acp/config.py +24 -0
  8. agentirc_cli-8.7.0/culture/clients/acp/culture.yaml +32 -0
  9. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/acp/daemon.py +11 -0
  10. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/acp/irc_transport.py +109 -18
  11. agentirc_cli-8.7.0/culture/clients/acp/telemetry.py +318 -0
  12. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/claude/agent_runner.py +71 -14
  13. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/claude/config.py +24 -0
  14. agentirc_cli-8.7.0/culture/clients/claude/culture.yaml +29 -0
  15. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/claude/daemon.py +11 -0
  16. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/claude/irc_transport.py +126 -35
  17. agentirc_cli-8.7.0/culture/clients/claude/telemetry.py +318 -0
  18. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/codex/agent_runner.py +60 -22
  19. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/codex/config.py +26 -0
  20. agentirc_cli-8.7.0/culture/clients/codex/culture.yaml +29 -0
  21. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/codex/daemon.py +11 -0
  22. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/codex/irc_transport.py +109 -18
  23. agentirc_cli-8.7.0/culture/clients/codex/telemetry.py +318 -0
  24. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/copilot/agent_runner.py +48 -6
  25. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/copilot/config.py +24 -0
  26. agentirc_cli-8.7.0/culture/clients/copilot/culture.yaml +29 -0
  27. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/copilot/daemon.py +11 -0
  28. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/copilot/irc_transport.py +109 -18
  29. agentirc_cli-8.7.0/culture/clients/copilot/telemetry.py +318 -0
  30. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/telemetry/metrics.py +13 -0
  31. agentirc_cli-8.7.0/docs/agentirc/harness-telemetry.md +302 -0
  32. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/agentirc/telemetry.md +77 -5
  33. agentirc_cli-8.7.0/docs/superpowers/plans/2026-04-28-otel-harness.md +272 -0
  34. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-24-otel-observability-design.md +1 -1
  35. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/packages/agent-harness/README.md +11 -0
  36. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/packages/agent-harness/config.py +24 -0
  37. agentirc_cli-8.7.0/packages/agent-harness/culture.yaml +28 -0
  38. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/packages/agent-harness/daemon.py +13 -1
  39. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/packages/agent-harness/irc_transport.py +108 -18
  40. agentirc_cli-8.7.0/packages/agent-harness/telemetry.py +315 -0
  41. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/pyproject.toml +2 -1
  42. agentirc_cli-8.7.0/tests/harness/conftest.py +89 -0
  43. agentirc_cli-8.7.0/tests/harness/test_agent_runner_acp.py +233 -0
  44. agentirc_cli-8.7.0/tests/harness/test_agent_runner_claude.py +449 -0
  45. agentirc_cli-8.7.0/tests/harness/test_agent_runner_codex.py +229 -0
  46. agentirc_cli-8.7.0/tests/harness/test_agent_runner_copilot.py +256 -0
  47. agentirc_cli-8.7.0/tests/harness/test_all_backends_parity.py +398 -0
  48. agentirc_cli-8.7.0/tests/harness/test_daemon_telemetry.py +72 -0
  49. agentirc_cli-8.7.0/tests/harness/test_irc_transport_propagation.py +447 -0
  50. agentirc_cli-8.7.0/tests/harness/test_record_llm_call.py +245 -0
  51. agentirc_cli-8.7.0/tests/harness/test_telemetry_module.py +264 -0
  52. agentirc_cli-8.7.0/tests/telemetry/__init__.py +0 -0
  53. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/_metrics_helpers.py +9 -0
  54. agentirc_cli-8.7.0/tests/telemetry/conftest.py +33 -0
  55. agentirc_cli-8.7.0/tests/telemetry/test_bot_event_dispatch_span.py +138 -0
  56. agentirc_cli-8.7.0/tests/telemetry/test_bot_run_span.py +91 -0
  57. agentirc_cli-8.7.0/tests/telemetry/test_metrics_bots.py +127 -0
  58. agentirc_cli-8.7.0/tests/telemetry/test_metrics_webhook.py +148 -0
  59. agentirc_cli-8.7.0/tests/telemetry/test_webhook_http_span.py +45 -0
  60. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/uv.lock +107 -1
  61. agentirc_cli-8.5.0/culture/clients/acp/culture.yaml +0 -17
  62. agentirc_cli-8.5.0/culture/clients/claude/culture.yaml +0 -14
  63. agentirc_cli-8.5.0/culture/clients/codex/culture.yaml +0 -14
  64. agentirc_cli-8.5.0/culture/clients/copilot/culture.yaml +0 -14
  65. agentirc_cli-8.5.0/packages/agent-harness/culture.yaml +0 -13
  66. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/.claude/agents/doc-test-alignment.md +0 -0
  67. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/.claude/skills/pr-review/SKILL.md +0 -0
  68. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/.claude/skills/run-tests/SKILL.md +0 -0
  69. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/.claude/skills/run-tests/scripts/test.sh +0 -0
  70. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/.flake8 +0 -0
  71. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/.github/workflows/docs-check.yml +0 -0
  72. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/.github/workflows/publish.yml +0 -0
  73. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/.github/workflows/security-checks.yml +0 -0
  74. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/.github/workflows/tests.yml +0 -0
  75. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/.gitignore +0 -0
  76. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/.markdownlint-cli2.yaml +0 -0
  77. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/.pr_agent.toml +0 -0
  78. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/.pre-commit-config.yaml +0 -0
  79. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/.pylintrc +0 -0
  80. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/CLAUDE.md +0 -0
  81. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/Gemfile +0 -0
  82. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/Gemfile.lock +0 -0
  83. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/LICENSE +0 -0
  84. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/README.md +0 -0
  85. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/SECURITY.md +0 -0
  86. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/_config.base.yml +0 -0
  87. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/_config.culture.yml +0 -0
  88. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/_data/sites.yml +0 -0
  89. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/_includes/head_custom.html +0 -0
  90. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/_sass/color_schemes/anthropic.scss +0 -0
  91. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/_sass/color_schemes/dark-terminal.scss +0 -0
  92. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/_sass/custom/custom.scss +0 -0
  93. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/assets/images/IMG_3183.png +0 -0
  94. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/assets/images/apple-touch-icon.png +0 -0
  95. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/assets/images/favicon-16x16.png +0 -0
  96. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/assets/images/favicon-32x32.png +0 -0
  97. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/assets/images/favicon.ico +0 -0
  98. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/assets/images/og-agentirc.png +0 -0
  99. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/assets/images/og-culture.png +0 -0
  100. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/__init__.py +0 -0
  101. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/__main__.py +0 -0
  102. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/CLAUDE.md +0 -0
  103. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/__init__.py +0 -0
  104. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/__main__.py +0 -0
  105. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/channel.py +0 -0
  106. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/client.py +0 -0
  107. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/config.py +0 -0
  108. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/docs/agentirc-architecture.md +0 -0
  109. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/docs/agentirc-features.md +0 -0
  110. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/docs/agentirc-skill.md +0 -0
  111. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/docs/agentirc.md +0 -0
  112. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/events.py +0 -0
  113. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/history_store.py +0 -0
  114. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/ircd.py +0 -0
  115. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/remote_client.py +0 -0
  116. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/room_store.py +0 -0
  117. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/rooms_util.py +0 -0
  118. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/server_link.py +0 -0
  119. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/skill.py +0 -0
  120. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/skills/__init__.py +0 -0
  121. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/skills/history.py +0 -0
  122. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/skills/icon.py +0 -0
  123. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/skills/rooms.py +0 -0
  124. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/skills/threads.py +0 -0
  125. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/thread_store.py +0 -0
  126. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/aio.py +0 -0
  127. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/bots/__init__.py +0 -0
  128. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/bots/config.py +0 -0
  129. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/bots/filter_dsl.py +0 -0
  130. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/bots/system/__init__.py +0 -0
  131. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/bots/system/welcome/__init__.py +0 -0
  132. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/bots/system/welcome/bot.yaml +0 -0
  133. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/bots/system/welcome/handler.py +0 -0
  134. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/bots/template_engine.py +0 -0
  135. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/bots/virtual_client.py +0 -0
  136. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/__init__.py +0 -0
  137. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/_passthrough.py +0 -0
  138. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/afi.py +0 -0
  139. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/agent.py +0 -0
  140. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/bot.py +0 -0
  141. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/channel.py +0 -0
  142. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/devex.py +0 -0
  143. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/introspect.py +0 -0
  144. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/mesh.py +0 -0
  145. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/server.py +0 -0
  146. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/shared/__init__.py +0 -0
  147. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/shared/constants.py +0 -0
  148. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/shared/display.py +0 -0
  149. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/shared/formatting.py +0 -0
  150. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/shared/ipc.py +0 -0
  151. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/shared/mesh.py +0 -0
  152. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/shared/process.py +0 -0
  153. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/skills.py +0 -0
  154. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/__init__.py +0 -0
  155. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/acp/__init__.py +0 -0
  156. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/acp/ipc.py +0 -0
  157. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/acp/message_buffer.py +0 -0
  158. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/acp/skill/SKILL.md +0 -0
  159. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/acp/skill/__init__.py +0 -0
  160. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/acp/skill/irc_client.py +0 -0
  161. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/acp/socket_server.py +0 -0
  162. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/acp/supervisor.py +0 -0
  163. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/acp/webhook.py +0 -0
  164. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/claude/__init__.py +0 -0
  165. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/claude/__main__.py +0 -0
  166. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/claude/ipc.py +0 -0
  167. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/claude/message_buffer.py +0 -0
  168. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/claude/skill/SKILL.md +0 -0
  169. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/claude/skill/__init__.py +0 -0
  170. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/claude/skill/irc_client.py +0 -0
  171. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/claude/socket_server.py +0 -0
  172. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/claude/supervisor.py +0 -0
  173. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/claude/webhook.py +0 -0
  174. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/codex/__init__.py +0 -0
  175. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/codex/ipc.py +0 -0
  176. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/codex/message_buffer.py +0 -0
  177. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/codex/skill/SKILL.md +0 -0
  178. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/codex/skill/__init__.py +0 -0
  179. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/codex/skill/irc_client.py +0 -0
  180. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/codex/socket_server.py +0 -0
  181. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/codex/supervisor.py +0 -0
  182. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/codex/webhook.py +0 -0
  183. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/copilot/__init__.py +0 -0
  184. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/copilot/ipc.py +0 -0
  185. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/copilot/message_buffer.py +0 -0
  186. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/copilot/skill/SKILL.md +0 -0
  187. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/copilot/skill/__init__.py +0 -0
  188. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/copilot/skill/irc_client.py +0 -0
  189. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/copilot/socket_server.py +0 -0
  190. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/copilot/supervisor.py +0 -0
  191. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/copilot/webhook.py +0 -0
  192. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/config.py +0 -0
  193. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/console/__init__.py +0 -0
  194. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/console/app.py +0 -0
  195. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/console/client.py +0 -0
  196. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/console/commands.py +0 -0
  197. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/console/status.py +0 -0
  198. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/console/widgets/__init__.py +0 -0
  199. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/console/widgets/chat.py +0 -0
  200. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/console/widgets/info_panel.py +0 -0
  201. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/console/widgets/sidebar.py +0 -0
  202. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/constants.py +0 -0
  203. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/credentials.py +0 -0
  204. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/formatting.py +0 -0
  205. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/learn_prompt.py +0 -0
  206. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/mesh_config.py +0 -0
  207. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/observer.py +0 -0
  208. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/overview/__init__.py +0 -0
  209. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/overview/collector.py +0 -0
  210. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/overview/model.py +0 -0
  211. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/overview/renderer_text.py +0 -0
  212. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/overview/renderer_web.py +0 -0
  213. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/overview/web/style.css +0 -0
  214. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/persistence.py +0 -0
  215. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/pidfile.py +0 -0
  216. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/protocol/__init__.py +0 -0
  217. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/protocol/commands.py +0 -0
  218. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/protocol/extensions/audit.md +0 -0
  219. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/protocol/extensions/events.md +0 -0
  220. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/protocol/extensions/federation.md +0 -0
  221. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/protocol/extensions/history.md +0 -0
  222. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/protocol/extensions/icons.md +0 -0
  223. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/protocol/extensions/rooms.md +0 -0
  224. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/protocol/extensions/tags.md +0 -0
  225. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/protocol/extensions/threads.md +0 -0
  226. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/protocol/extensions/tracing.md +0 -0
  227. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/protocol/message.py +0 -0
  228. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/protocol/protocol-index.md +0 -0
  229. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/protocol/replies.py +0 -0
  230. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/skills/culture/SKILL.md +0 -0
  231. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/telemetry/__init__.py +0 -0
  232. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/telemetry/audit.py +0 -0
  233. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/telemetry/context.py +0 -0
  234. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/telemetry/tracing.py +0 -0
  235. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/README.md +0 -0
  236. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/agentirc/architecture-overview.md +0 -0
  237. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/agentirc/audit.md +0 -0
  238. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/agentirc/bots.md +0 -0
  239. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/agentirc/events.md +0 -0
  240. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/agentirc/index.md +0 -0
  241. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/agentirc/otelcol-template.yaml +0 -0
  242. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/agentirc/why-agentirc.md +0 -0
  243. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/culture/agent-lifecycle.md +0 -0
  244. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/culture/choose-a-harness.md +0 -0
  245. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/culture/features.md +0 -0
  246. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/culture/index.md +0 -0
  247. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/culture/mental-model.md +0 -0
  248. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/culture/operate.md +0 -0
  249. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/culture/patterns.md +0 -0
  250. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/culture/quickstart.md +0 -0
  251. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/culture/reflective-development.md +0 -0
  252. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/culture/vision-patterns-index.md +0 -0
  253. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/culture/vision.md +0 -0
  254. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/culture/what-is-culture.md +0 -0
  255. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/architecture/agent-harness-spec.md +0 -0
  256. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/architecture/index.md +0 -0
  257. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/architecture/layers.md +0 -0
  258. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/architecture/subsites.md +0 -0
  259. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/architecture/threads.md +0 -0
  260. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/cli/afi.md +0 -0
  261. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/cli/commands.md +0 -0
  262. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/cli/devex.md +0 -0
  263. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/cli/index.md +0 -0
  264. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/console.md +0 -0
  265. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/harnesses/acp.md +0 -0
  266. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/harnesses/claude.md +0 -0
  267. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/harnesses/codex.md +0 -0
  268. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/harnesses/copilot.md +0 -0
  269. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/harnesses/index.md +0 -0
  270. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/index.md +0 -0
  271. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/server/architecture.md +0 -0
  272. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/server/config.md +0 -0
  273. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/server/deployment.md +0 -0
  274. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/server/index.md +0 -0
  275. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/server/security.md +0 -0
  276. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/resources/github-copilot-sdk-instructions.md +0 -0
  277. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/resources/positioning.md +0 -0
  278. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/concepts/federation.md +0 -0
  279. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/concepts/harnesses.md +0 -0
  280. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/concepts/humans-and-agents.md +0 -0
  281. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/concepts/index.md +0 -0
  282. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/concepts/persistence.md +0 -0
  283. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/concepts/rooms.md +0 -0
  284. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/demos/magic-demo.md +0 -0
  285. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/guides/first-session.md +0 -0
  286. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/guides/index.md +0 -0
  287. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/guides/join-as-human.md +0 -0
  288. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/guides/local-setup.md +0 -0
  289. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/guides/multi-machine.md +0 -0
  290. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/use-cases/01-pair-programming.md +0 -0
  291. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/use-cases/02-code-review-ensemble.md +0 -0
  292. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/use-cases/03-cross-server-delegation.md +0 -0
  293. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/use-cases/04-knowledge-propagation.md +0 -0
  294. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/use-cases/05-the-observer.md +0 -0
  295. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/use-cases/06-cross-server-ops.md +0 -0
  296. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/use-cases/07-supervisor-intervention.md +0 -0
  297. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/use-cases/08-apps-as-agents.md +0 -0
  298. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/use-cases/09-research-swarm.md +0 -0
  299. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/use-cases/10-agent-lifecycle.md +0 -0
  300. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/use-cases-index.md +0 -0
  301. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-03-19-layer1-core-irc.md +0 -0
  302. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-03-21-layer5-agent-harness.md +0 -0
  303. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-03-30-overview.md +0 -0
  304. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-03-30-rooms-management.md +0 -0
  305. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-04-02-conversation-threads.md +0 -0
  306. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-04-02-ops-tooling.md +0 -0
  307. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-04-04-culture-rename.md +0 -0
  308. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-04-05-docs-speak-culture.md +0 -0
  309. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-04-06-console-chat.md +0 -0
  310. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-04-09-decentralized-agent-config.md +0 -0
  311. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-04-12-console-enhancements.md +0 -0
  312. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-04-15-mesh-events.md +0 -0
  313. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-04-18-culture-dev-positioning.md +0 -0
  314. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-04-22-agex-integration.md +0 -0
  315. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-04-24-otel-foundation.md +0 -0
  316. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-04-25-otel-federation.md +0 -0
  317. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-04-26-otel-metrics.md +0 -0
  318. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-04-27-otel-audit.md +0 -0
  319. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-03-19-agentirc-design.md +0 -0
  320. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-03-21-layer5-agent-harness-design.md +0 -0
  321. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-03-30-overview-design.md +0 -0
  322. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-03-30-rooms-management-design.md +0 -0
  323. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-02-conversation-threads-design.md +0 -0
  324. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-02-ops-tooling-design.md +0 -0
  325. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-03-bots-webhooks-design.md +0 -0
  326. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-04-culture-rename-design.md +0 -0
  327. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-05-docs-speak-culture-design.md +0 -0
  328. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-05-lifecycle-reframe-design.md +0 -0
  329. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-06-cli-reorganization-design.md +0 -0
  330. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-06-console-chat-design.md +0 -0
  331. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-07-entity-archiving-design.md +0 -0
  332. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-07-reflective-development-reframe-design.md +0 -0
  333. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-08-reflective-development-deepening-design.md +0 -0
  334. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-09-decentralized-agent-config-design.md +0 -0
  335. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-12-console-enhancements-design.md +0 -0
  336. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-15-mesh-events-design.md +0 -0
  337. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-17-sites-repositioning-design.md +0 -0
  338. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-18-culture-dev-positioning-design.md +0 -0
  339. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-22-agex-integration-design.md +0 -0
  340. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/favicon.ico +0 -0
  341. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/packages/agent-harness/ipc.py +0 -0
  342. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/packages/agent-harness/message_buffer.py +0 -0
  343. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/packages/agent-harness/skill/SKILL.md +0 -0
  344. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/packages/agent-harness/skill/irc_client.py +0 -0
  345. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/packages/agent-harness/socket_server.py +0 -0
  346. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/packages/agent-harness/webhook.py +0 -0
  347. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/plugins/claude-code/.claude-plugin/plugin.json +0 -0
  348. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/plugins/claude-code/skills/culture/SKILL.md +0 -0
  349. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/plugins/claude-code/skills/irc/SKILL.md +0 -0
  350. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/plugins/codex/skills/culture-irc/SKILL.md +0 -0
  351. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/robots.txt +0 -0
  352. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/sitemap-agentirc.html +0 -0
  353. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/sitemap-main.html +0 -0
  354. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/sitemap.html +0 -0
  355. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/sonar-project.properties +0 -0
  356. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/__init__.py +0 -0
  357. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/conftest.py +0 -0
  358. {agentirc_cli-8.5.0/tests/telemetry → agentirc_cli-8.7.0/tests/harness}/__init__.py +0 -0
  359. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/_fakes.py +0 -0
  360. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_audit_emit.py +0 -0
  361. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_audit_federation.py +0 -0
  362. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_audit_lifecycle.py +0 -0
  363. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_audit_module.py +0 -0
  364. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_audit_parse_error.py +0 -0
  365. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_config.py +0 -0
  366. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_config_load.py +0 -0
  367. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_context.py +0 -0
  368. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_dispatch_span.py +0 -0
  369. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_emit_event_span.py +0 -0
  370. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_federation_propagation.py +0 -0
  371. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_metrics_clients.py +0 -0
  372. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_metrics_events.py +0 -0
  373. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_metrics_init.py +0 -0
  374. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_metrics_irc.py +0 -0
  375. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_metrics_s2s.py +0 -0
  376. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_metrics_trace_inbound.py +0 -0
  377. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_outbound_inject.py +0 -0
  378. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_parse_error.py +0 -0
  379. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_privmsg_span.py +0 -0
  380. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_s2s_dispatch_span.py +0 -0
  381. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_s2s_relay_span.py +0 -0
  382. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_s2s_session_span.py +0 -0
  383. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_server_init.py +0 -0
  384. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_server_link_inject.py +0 -0
  385. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_session_span.py +0 -0
  386. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_tracing.py +0 -0
  387. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_acp_daemon.py +0 -0
  388. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_agent_runner.py +0 -0
  389. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_archive.py +0 -0
  390. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_bot.py +0 -0
  391. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_bot_config.py +0 -0
  392. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_bot_config_fires_event_toplevel.py +0 -0
  393. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_bot_manager.py +0 -0
  394. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_bots_integration.py +0 -0
  395. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_channel.py +0 -0
  396. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_channel_cli.py +0 -0
  397. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_cli_afi.py +0 -0
  398. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_cli_devex.py +0 -0
  399. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_cli_introspect.py +0 -0
  400. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_cli_passthrough.py +0 -0
  401. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_codex_daemon.py +0 -0
  402. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_connection.py +0 -0
  403. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_console_chat_markdown.py +0 -0
  404. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_console_client.py +0 -0
  405. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_console_commands.py +0 -0
  406. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_console_connection.py +0 -0
  407. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_console_fixes_224_227.py +0 -0
  408. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_console_icons.py +0 -0
  409. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_console_integration.py +0 -0
  410. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_console_status.py +0 -0
  411. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_copilot_daemon.py +0 -0
  412. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_credentials.py +0 -0
  413. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_culture_config.py +0 -0
  414. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_daemon.py +0 -0
  415. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_daemon_config.py +0 -0
  416. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_daemon_ipc.py +0 -0
  417. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_discovery.py +0 -0
  418. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_display.py +0 -0
  419. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_events_basic.py +0 -0
  420. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_events_bot_chain.py +0 -0
  421. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_events_bot_trigger.py +0 -0
  422. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_events_cap_fallback.py +0 -0
  423. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_events_catalog.py +0 -0
  424. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_events_federation.py +0 -0
  425. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_events_history.py +0 -0
  426. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_events_lifecycle.py +0 -0
  427. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_events_reserved_nick.py +0 -0
  428. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_federation.py +0 -0
  429. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_filter_dsl.py +0 -0
  430. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_history.py +0 -0
  431. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_http_listener.py +0 -0
  432. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_integration_layer5.py +0 -0
  433. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_ipc.py +0 -0
  434. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_irc_transport.py +0 -0
  435. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_irc_transport_tags.py +0 -0
  436. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_learn_prompt.py +0 -0
  437. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_link_reconnect.py +0 -0
  438. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_manifest_config.py +0 -0
  439. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_mention_alias.py +0 -0
  440. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_mention_target_cleanup.py +0 -0
  441. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_mention_warning.py +0 -0
  442. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_mentions.py +0 -0
  443. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_mesh_config.py +0 -0
  444. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_mesh_readiness.py +0 -0
  445. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_message.py +0 -0
  446. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_message_buffer.py +0 -0
  447. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_message_tags.py +0 -0
  448. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_messaging.py +0 -0
  449. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_migrate_cli.py +0 -0
  450. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_modes.py +0 -0
  451. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_overview_cli.py +0 -0
  452. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_overview_collector.py +0 -0
  453. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_overview_model.py +0 -0
  454. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_overview_renderer.py +0 -0
  455. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_overview_web.py +0 -0
  456. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_persistence.py +0 -0
  457. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_persistence_timeout.py +0 -0
  458. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_pidfile.py +0 -0
  459. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_poll_loop.py +0 -0
  460. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_register_cli.py +0 -0
  461. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_room_persistence.py +0 -0
  462. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_rooms.py +0 -0
  463. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_rooms_federation.py +0 -0
  464. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_rooms_integration.py +0 -0
  465. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_server_icon_skill.py +0 -0
  466. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_setup_update_cli.py +0 -0
  467. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_skill_client.py +0 -0
  468. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_skill_docs.py +0 -0
  469. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_skills.py +0 -0
  470. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_socket_server.py +0 -0
  471. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_supervisor.py +0 -0
  472. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_template_engine.py +0 -0
  473. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_thread_buffer.py +0 -0
  474. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_threads.py +0 -0
  475. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_virtual_client.py +0 -0
  476. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_wait_for_port.py +0 -0
  477. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_webhook.py +0 -0
  478. {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_welcome_bot.py +0 -0
@@ -4,6 +4,35 @@ 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
+ ## [8.7.0] - 2026-04-26
8
+
9
+ ### Added
10
+
11
+ - OTEL bot instrumentation (Plan 7): bot.event.dispatch and bot.run spans, culture.bot.invocations counter, culture.bot.webhook.duration histogram, aiohttp-server auto-instrumentation on the webhook listener.
12
+
13
+ ### Changed
14
+
15
+ - docs/agentirc/telemetry.md updated with the 8.7.0 section; harness-telemetry.md cross-link updated.
16
+
17
+ ## [8.6.0] - 2026-04-26
18
+
19
+ ### Added
20
+
21
+ - Harness-side OTEL: 3 spans (harness.irc.connect, harness.irc.message.handle, harness.llm.call) and 4 LLM metrics (culture.harness.llm.tokens.input/output, call.duration, calls).
22
+ - W3C traceparent injection on outbound IRC + extraction on inbound — single trace_id now spans server, federation, and harness in the cross-process tree.
23
+ - Per-backend telemetry citation across claude/codex/copilot/acp with all-backends parity test (24 tests across 6 dimensions) locking down drift.
24
+ - docs/agentirc/harness-telemetry.md — new operator guide for the harness OTEL pillar.
25
+
26
+ ### Changed
27
+
28
+ - packages/agent-harness/{telemetry.py,config.py,culture.yaml,irc_transport.py,daemon.py} — reference module for the citation pattern.
29
+ - culture/clients/{claude,codex,copilot,acp}/{telemetry.py,config.py,culture.yaml,irc_transport.py,daemon.py,agent_runner.py} — telemetry citation, harness.llm.call span wrap, record_llm_call invocation.
30
+ - tests/harness/ — 70 new tests (24 parity + 46 module/runner/transport/daemon).
31
+
32
+ ### Fixed
33
+
34
+ - Code-quality fixes from review: zero-token usage extraction (0 no longer silenced), tracer-name from constant (no hardcoded strings), module-top imports of record_llm_call across all 4 backends.
35
+
7
36
  ## [8.5.0] - 2026-04-25
8
37
 
9
38
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentirc-cli
3
- Version: 8.5.0
3
+ Version: 8.7.0
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
@@ -20,6 +20,7 @@ Requires-Dist: claude-agent-sdk>=0.1
20
20
  Requires-Dist: mistune>=3.0
21
21
  Requires-Dist: opentelemetry-api>=1.25
22
22
  Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.25
23
+ Requires-Dist: opentelemetry-instrumentation-aiohttp-server>=0.46b0
23
24
  Requires-Dist: opentelemetry-sdk>=1.25
24
25
  Requires-Dist: opentelemetry-semantic-conventions>=0.46b0
25
26
  Requires-Dist: pyyaml>=6.0
@@ -8,6 +8,8 @@ import time
8
8
  from pathlib import Path
9
9
  from typing import TYPE_CHECKING, Any
10
10
 
11
+ from opentelemetry import trace as _otel_trace
12
+
11
13
  from culture.agentirc.skill import Event, EventType
12
14
  from culture.bots.config import BOTS_DIR, BotConfig
13
15
  from culture.bots.template_engine import render_fallback, render_template
@@ -125,19 +127,28 @@ class Bot:
125
127
 
126
128
  Returns the rendered message text.
127
129
  """
128
- if not self.active or not self.virtual_client:
129
- raise RuntimeError(f"Bot {self.config.name} is not active")
130
-
131
- message = await self._resolve_message(payload)
132
- if not message:
133
- return ""
134
-
135
- if self.config.mention:
136
- message = f"@{self.config.mention} {message}"
137
-
138
- await self._deliver(message, payload)
139
- await self._maybe_fire_event(payload)
140
- return message
130
+ # Span opens before the active-check so, if handle() is invoked for an
131
+ # inactive bot, the failure still surfaces in tracing with ERROR
132
+ # status and bot.name set instead of only raising.
133
+ with _otel_trace.get_tracer("culture.agentirc").start_as_current_span(
134
+ "bot.run",
135
+ attributes={"bot.name": self.config.name},
136
+ ) as span:
137
+ if not self.active or not self.virtual_client:
138
+ span.set_status(_otel_trace.StatusCode.ERROR, "bot not active")
139
+ raise RuntimeError(f"Bot {self.config.name} is not active")
140
+
141
+ message = await self._resolve_message(payload)
142
+ if not message:
143
+ span.set_attribute("bot.run.empty_message", True)
144
+ return ""
145
+
146
+ if self.config.mention:
147
+ message = f"@{self.config.mention} {message}"
148
+
149
+ await self._deliver(message, payload)
150
+ await self._maybe_fire_event(payload)
151
+ return message
141
152
 
142
153
  async def _resolve_message(self, payload: dict) -> str:
143
154
  """Render the message from custom handler or template."""
@@ -2,9 +2,12 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import asyncio
5
6
  import logging
6
7
  from typing import TYPE_CHECKING
7
8
 
9
+ from opentelemetry import trace as _otel_trace
10
+
8
11
  from culture.bots.bot import Bot
9
12
  from culture.bots.config import (
10
13
  BOT_CONFIG_FILE,
@@ -88,32 +91,58 @@ class BotManager:
88
91
  async def on_event(self, event) -> None:
89
92
  """Evaluate event-triggered bots against an event and dispatch matches."""
90
93
  # Snapshot: handle() may call emit_event() which re-enters on_event().
91
- bots_snapshot = list(self.bots.values())
92
- for bot in bots_snapshot:
93
- cfg = bot.config
94
- if cfg.trigger_type != "event":
95
- continue
96
- compiled = getattr(cfg, "_compiled_filter", None)
97
- if compiled is None:
98
- continue
99
- ctx = {
100
- "type": event.type.value if hasattr(event.type, "value") else str(event.type),
101
- "channel": event.channel,
102
- "nick": event.nick,
103
- "data": dict(event.data),
104
- }
105
- try:
106
- if not evaluate(compiled, ctx):
107
- continue
108
- except Exception:
109
- logger.exception("Filter evaluation failed for bot %s", cfg.name)
110
- continue
111
- if not await self._try_start_bot(bot):
112
- continue
94
+ ctx = {
95
+ "type": event.type.value if hasattr(event.type, "value") else str(event.type),
96
+ "channel": event.channel,
97
+ "nick": event.nick,
98
+ "data": dict(event.data),
99
+ }
100
+ for bot in list(self.bots.values()):
101
+ if self._matches_event(bot, ctx):
102
+ await self._dispatch_to_bot(bot, ctx)
103
+
104
+ def _matches_event(self, bot: Bot, ctx: dict) -> bool:
105
+ """True iff `bot` is event-triggered and its filter accepts `ctx`."""
106
+ cfg = bot.config
107
+ if cfg.trigger_type != "event":
108
+ return False
109
+ compiled = getattr(cfg, "_compiled_filter", None)
110
+ if compiled is None:
111
+ return False
112
+ try:
113
+ return bool(evaluate(compiled, ctx))
114
+ except Exception:
115
+ logger.exception("Filter evaluation failed for bot %s", cfg.name)
116
+ return False
117
+
118
+ async def _dispatch_to_bot(self, bot: Bot, ctx: dict) -> None:
119
+ """Lazily start the bot and run handle() inside a bot.event.dispatch span."""
120
+ if not await self._try_start_bot(bot):
121
+ return
122
+ cfg = bot.config
123
+ event_type_str = ctx["type"]
124
+ with _otel_trace.get_tracer("culture.agentirc").start_as_current_span(
125
+ "bot.event.dispatch",
126
+ attributes={"bot.name": cfg.name, "event.type": event_type_str},
127
+ ) as span:
128
+ outcome = "success"
113
129
  try:
114
130
  await bot.handle({"event": ctx})
115
- except Exception:
116
- logger.exception("Bot %s handle() failed for event %s", cfg.name, event.type)
131
+ except asyncio.CancelledError:
132
+ raise
133
+ except Exception as exc:
134
+ outcome = "error"
135
+ span.set_status(_otel_trace.StatusCode.ERROR, str(exc))
136
+ logger.exception("Bot %s handle() failed for event %s", cfg.name, ctx["type"])
137
+ finally:
138
+ self.server.metrics.bot_invocations.add(
139
+ 1,
140
+ {
141
+ "bot": cfg.name,
142
+ "event.type": event_type_str,
143
+ "outcome": outcome,
144
+ },
145
+ )
117
146
 
118
147
  def load_system_bots(self) -> None:
119
148
  """Discover and register system bots from the package."""
@@ -4,9 +4,11 @@ from __future__ import annotations
4
4
 
5
5
  import json
6
6
  import logging
7
+ import time
7
8
  from typing import TYPE_CHECKING
8
9
 
9
10
  from aiohttp import web
11
+ from opentelemetry.instrumentation.aiohttp_server import AioHttpServerInstrumentor
10
12
 
11
13
  if TYPE_CHECKING:
12
14
  from culture.bots.bot_manager import BotManager
@@ -25,7 +27,16 @@ class HttpListener:
25
27
  self._runner: web.AppRunner | None = None
26
28
 
27
29
  async def start(self) -> None:
28
- self._app = web.Application()
30
+ # Patch aiohttp.web.Application to auto-inject the OTEL server
31
+ # middleware. Deferred from import time so just importing this module
32
+ # has no side effect. Re-instrument each start() so the captured
33
+ # tracer/meter rebinds to the *current* TracerProvider — important for
34
+ # tests that swap providers between runs, harmless in production.
35
+ instrumentor = AioHttpServerInstrumentor()
36
+ if instrumentor.is_instrumented_by_opentelemetry:
37
+ instrumentor.uninstrument()
38
+ instrumentor.instrument()
39
+ self._app = web.Application(middlewares=[self._record_webhook_duration])
29
40
  self._app.router.add_get("/health", self._handle_health)
30
41
  self._app.router.add_post("/{bot_name}", self._handle_webhook)
31
42
 
@@ -41,6 +52,29 @@ class HttpListener:
41
52
  self._runner = None
42
53
  self._app = None
43
54
 
55
+ @web.middleware
56
+ async def _record_webhook_duration(self, request, handler):
57
+ """Record per-request duration into culture.bot.webhook.duration."""
58
+ bot_name = request.match_info.get("bot_name") or "_unrouted"
59
+ start = time.perf_counter()
60
+ # Default for the "handler raised a non-HTTPException" path: aiohttp
61
+ # converts unhandled exceptions to 500 responses outside this
62
+ # middleware, so the histogram should report 5xx for them.
63
+ status_class = "5xx"
64
+ try:
65
+ response = await handler(request)
66
+ status_class = f"{response.status // 100}xx"
67
+ return response
68
+ except web.HTTPException as exc:
69
+ status_class = f"{exc.status // 100}xx"
70
+ raise
71
+ finally:
72
+ duration = time.perf_counter() - start
73
+ self.bot_manager.server.metrics.bot_webhook_duration.record(
74
+ duration,
75
+ {"bot": bot_name, "status_class": status_class},
76
+ )
77
+
44
78
  async def _handle_health(self, request: web.Request) -> web.Response:
45
79
  return web.json_response({"status": "ok"})
46
80
 
@@ -12,9 +12,16 @@ import logging
12
12
  import os
13
13
  import shutil
14
14
  import tempfile
15
- from typing import Any, Awaitable, Callable
15
+ import time
16
+ from typing import TYPE_CHECKING, Any, Awaitable, Callable
17
+
18
+ from opentelemetry import trace as _otel_trace
16
19
 
17
20
  from culture.aio import maybe_await
21
+ from culture.clients.acp.telemetry import _HARNESS_TRACER_NAME, record_llm_call
22
+
23
+ if TYPE_CHECKING:
24
+ from culture.clients.acp.telemetry import HarnessMetricsRegistry
18
25
 
19
26
  logger = logging.getLogger(__name__)
20
27
 
@@ -36,6 +43,8 @@ class ACPAgentRunner:
36
43
  on_exit: Callable[[int], Awaitable[None]] | None = None,
37
44
  on_message: Callable[[dict[str, Any]], Awaitable[None]] | None = None,
38
45
  on_turn_error: Callable[[], Awaitable[None] | None] | None = None,
46
+ metrics: HarnessMetricsRegistry | None = None,
47
+ nick: str = "",
39
48
  ) -> None:
40
49
  self.model = model
41
50
  self.directory = directory
@@ -44,6 +53,8 @@ class ACPAgentRunner:
44
53
  self.on_exit = on_exit
45
54
  self.on_message = on_message
46
55
  self.on_turn_error = on_turn_error
56
+ self._metrics = metrics
57
+ self._nick = nick
47
58
 
48
59
  self._isolated_home: str | None = None
49
60
  self._process: asyncio.subprocess.Process | None = None
@@ -431,16 +442,47 @@ class ACPAgentRunner:
431
442
 
432
443
  async def _execute_single_prompt(self, text: str) -> None:
433
444
  """Send one prompt and handle its result, managing the busy flag."""
434
- try:
435
- self._busy = True
436
- resp = await self._send_prompt_with_retry(text)
437
- await self._handle_prompt_result(resp)
438
- except Exception:
439
- logger.exception("ACP turn error")
440
- if self.on_turn_error:
441
- await maybe_await(self.on_turn_error())
442
- finally:
443
- self._busy = False
445
+ start_perf = time.perf_counter()
446
+ outcome = "success"
447
+ tracer = _otel_trace.get_tracer(_HARNESS_TRACER_NAME)
448
+ with tracer.start_as_current_span(
449
+ "harness.llm.call",
450
+ attributes={
451
+ "harness.backend": "acp",
452
+ "harness.model": self.model,
453
+ "harness.nick": self._nick,
454
+ },
455
+ ):
456
+ try:
457
+ self._busy = True
458
+ resp = await self._send_prompt_with_retry(text)
459
+ await self._handle_prompt_result(resp)
460
+ except TimeoutError: # bubbles from _send_prompt_with_retry's retry-then-fail
461
+ outcome = "timeout"
462
+ logger.exception("ACP turn timeout")
463
+ if self.on_turn_error:
464
+ await maybe_await(self.on_turn_error())
465
+ except Exception:
466
+ outcome = "error"
467
+ logger.exception("ACP turn error")
468
+ if self.on_turn_error:
469
+ await maybe_await(self.on_turn_error())
470
+ finally:
471
+ self._busy = False
472
+ duration_ms = (time.perf_counter() - start_perf) * 1000.0
473
+ if self._metrics is not None:
474
+ # ACP token usage MAY arrive in session/update stopReason payload;
475
+ # current implementation does not extract — usage=None for v1.
476
+ # When we add extraction (per backing agent), thread through here.
477
+ record_llm_call(
478
+ self._metrics,
479
+ backend="acp",
480
+ model=self.model,
481
+ nick=self._nick,
482
+ usage=None,
483
+ duration_ms=duration_ms,
484
+ outcome=outcome,
485
+ )
444
486
 
445
487
  async def _prompt_loop(self) -> None:
446
488
  """Process queued prompts one at a time."""
@@ -62,6 +62,27 @@ class AgentConfig:
62
62
  icon: str | None = None
63
63
 
64
64
 
65
+ @dataclass
66
+ class TelemetryConfig:
67
+ """OpenTelemetry settings for the agent harness.
68
+
69
+ ``enabled: false`` by default so freshly installed harnesses don't
70
+ try to connect to a non-existent OTLP collector. Flip to ``true``
71
+ once your collector is running.
72
+ """
73
+
74
+ enabled: bool = False
75
+ service_name: str = "culture.harness.acp"
76
+ otlp_endpoint: str = "http://localhost:4317"
77
+ otlp_protocol: str = "grpc" # grpc | http/protobuf (only grpc supported initially)
78
+ otlp_timeout_ms: int = 5000
79
+ otlp_compression: str = "gzip"
80
+ traces_enabled: bool = True
81
+ traces_sampler: str = "parentbased_always_on"
82
+ metrics_enabled: bool = True
83
+ metrics_export_interval_ms: int = 10000
84
+
85
+
65
86
  @dataclass
66
87
  class DaemonConfig:
67
88
  """Top-level daemon configuration."""
@@ -69,6 +90,7 @@ class DaemonConfig:
69
90
  server: ServerConnConfig = field(default_factory=ServerConnConfig)
70
91
  supervisor: SupervisorConfig = field(default_factory=SupervisorConfig)
71
92
  webhooks: WebhookConfig = field(default_factory=WebhookConfig)
93
+ telemetry: TelemetryConfig = field(default_factory=TelemetryConfig)
72
94
  buffer_size: int = 500
73
95
  poll_interval: int = 60
74
96
  sleep_start: str = "23:00"
@@ -91,6 +113,7 @@ def load_config(path: str | Path) -> DaemonConfig:
91
113
  supervisor = SupervisorConfig(**raw.get("supervisor", {}))
92
114
 
93
115
  webhooks = WebhookConfig(**raw.get("webhooks", {}))
116
+ telemetry = TelemetryConfig(**raw.get("telemetry", {}))
94
117
 
95
118
  agents = []
96
119
  known_agent_fields = {f.name for f in AgentConfig.__dataclass_fields__.values()}
@@ -102,6 +125,7 @@ def load_config(path: str | Path) -> DaemonConfig:
102
125
  server=server,
103
126
  supervisor=supervisor,
104
127
  webhooks=webhooks,
128
+ telemetry=telemetry,
105
129
  buffer_size=raw.get("buffer_size", 500),
106
130
  poll_interval=raw.get("poll_interval", 60),
107
131
  sleep_start=raw.get("sleep_start", "23:00"),
@@ -0,0 +1,32 @@
1
+ suffix: harness-acp
2
+ backend: claude
3
+ model: claude-opus-4-6
4
+ channels:
5
+ - "#harness"
6
+ acp_command:
7
+ - opencode
8
+ - acp
9
+ system_prompt: |
10
+ You maintain the ACP agent backend in culture/clients/acp/.
11
+ Listen on #harness for propagation instructions from spark-harness.
12
+ Apply changes using the citation pattern (cite, don't import),
13
+ adapting for ACP (Cline, OpenCode, Kiro)
14
+ specifics (agent_runner.py, supervisor.py).
15
+ tags:
16
+ - harness
17
+ - acp
18
+
19
+ # OpenTelemetry configuration for the agent harness.
20
+ # Set enabled: true once your OTLP collector is running.
21
+ # See docs/agentirc/harness-telemetry.md for a setup guide.
22
+ telemetry:
23
+ enabled: false # master switch — flip to true to start exporting
24
+ service_name: culture.harness.acp # overridden per-backend (e.g. culture.harness.acp)
25
+ otlp_endpoint: http://localhost:4317 # OTLP/gRPC receiver endpoint
26
+ otlp_protocol: grpc # grpc or http/protobuf
27
+ otlp_timeout_ms: 5000 # export request timeout in milliseconds
28
+ otlp_compression: gzip # gzip | none
29
+ traces_enabled: true # enable distributed tracing
30
+ traces_sampler: parentbased_always_on # honor the server's sampling decision
31
+ metrics_enabled: true # enable LLM call metrics export
32
+ metrics_export_interval_ms: 10000 # how often to push metric batches (ms)
@@ -25,6 +25,7 @@ from culture.clients.acp.irc_transport import IRCTransport
25
25
  from culture.clients.acp.message_buffer import MessageBuffer
26
26
  from culture.clients.acp.socket_server import SocketServer
27
27
  from culture.clients.acp.supervisor import Supervisor, make_sdk_evaluate_fn
28
+ from culture.clients.acp.telemetry import init_harness_telemetry
28
29
  from culture.clients.acp.webhook import AlertEvent, WebhookClient
29
30
  from culture.pidfile import remove_pid, write_pid
30
31
 
@@ -71,6 +72,8 @@ class ACPDaemon:
71
72
  self._socket_server: SocketServer | None = None
72
73
  self._agent_runner: ACPAgentRunner | None = None
73
74
  self._supervisor: Supervisor | None = None
75
+ self._tracer = None
76
+ self._metrics = None
74
77
 
75
78
  # FIFO queue of relay targets — each @mention enqueues a target,
76
79
  # each agent response dequeues one, ensuring correct routing even
@@ -134,6 +137,9 @@ class ACPDaemon:
134
137
  self._pid_name = f"agent-{self.agent.nick}"
135
138
  write_pid(self._pid_name, os.getpid())
136
139
 
140
+ # 0.5. OTEL telemetry (if telemetry.enabled, installs SDK providers; else no-op).
141
+ self._tracer, self._metrics = init_harness_telemetry(self.config)
142
+
137
143
  # 1. Message buffer
138
144
  self._buffer = MessageBuffer(max_per_channel=self.config.buffer_size)
139
145
 
@@ -148,6 +154,9 @@ class ACPDaemon:
148
154
  on_mention=self._on_mention,
149
155
  tags=list(self.agent.tags),
150
156
  on_roominvite=self._on_roominvite,
157
+ tracer=self._tracer,
158
+ metrics=self._metrics,
159
+ backend="acp",
151
160
  )
152
161
  await self._transport.connect()
153
162
 
@@ -389,6 +398,8 @@ class ACPDaemon:
389
398
  on_exit=self._on_agent_exit,
390
399
  on_message=self._on_agent_message,
391
400
  on_turn_error=self._on_turn_error,
401
+ metrics=self._metrics,
402
+ nick=self.agent.nick,
392
403
  )
393
404
  # Absorb the system prompt response without relaying to IRC
394
405
  self._mention_targets.append(None)