agentirc-cli 8.4.0__tar.gz → 8.5.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 (449) hide show
  1. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/CHANGELOG.md +15 -0
  2. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/PKG-INFO +1 -1
  3. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/agentirc/client.py +45 -0
  4. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/agentirc/config.py +7 -0
  5. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/agentirc/ircd.py +35 -2
  6. agentirc_cli-8.5.0/culture/protocol/extensions/audit.md +109 -0
  7. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/telemetry/__init__.py +5 -0
  8. agentirc_cli-8.5.0/culture/telemetry/audit.py +380 -0
  9. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/telemetry/metrics.py +12 -0
  10. agentirc_cli-8.5.0/docs/agentirc/audit.md +154 -0
  11. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/agentirc/telemetry.md +30 -4
  12. agentirc_cli-8.5.0/docs/superpowers/plans/2026-04-27-otel-audit.md +247 -0
  13. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/pyproject.toml +1 -1
  14. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/conftest.py +22 -2
  15. agentirc_cli-8.5.0/tests/telemetry/test_audit_emit.py +145 -0
  16. agentirc_cli-8.5.0/tests/telemetry/test_audit_federation.py +132 -0
  17. agentirc_cli-8.5.0/tests/telemetry/test_audit_lifecycle.py +69 -0
  18. agentirc_cli-8.5.0/tests/telemetry/test_audit_module.py +306 -0
  19. agentirc_cli-8.5.0/tests/telemetry/test_audit_parse_error.py +177 -0
  20. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/uv.lock +1 -1
  21. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/.claude/agents/doc-test-alignment.md +0 -0
  22. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/.claude/skills/pr-review/SKILL.md +0 -0
  23. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/.claude/skills/run-tests/SKILL.md +0 -0
  24. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/.claude/skills/run-tests/scripts/test.sh +0 -0
  25. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/.flake8 +0 -0
  26. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/.github/workflows/docs-check.yml +0 -0
  27. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/.github/workflows/publish.yml +0 -0
  28. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/.github/workflows/security-checks.yml +0 -0
  29. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/.github/workflows/tests.yml +0 -0
  30. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/.gitignore +0 -0
  31. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/.markdownlint-cli2.yaml +0 -0
  32. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/.pr_agent.toml +0 -0
  33. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/.pre-commit-config.yaml +0 -0
  34. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/.pylintrc +0 -0
  35. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/CLAUDE.md +0 -0
  36. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/Gemfile +0 -0
  37. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/Gemfile.lock +0 -0
  38. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/LICENSE +0 -0
  39. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/README.md +0 -0
  40. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/SECURITY.md +0 -0
  41. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/_config.base.yml +0 -0
  42. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/_config.culture.yml +0 -0
  43. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/_data/sites.yml +0 -0
  44. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/_includes/head_custom.html +0 -0
  45. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/_sass/color_schemes/anthropic.scss +0 -0
  46. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/_sass/color_schemes/dark-terminal.scss +0 -0
  47. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/_sass/custom/custom.scss +0 -0
  48. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/assets/images/IMG_3183.png +0 -0
  49. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/assets/images/apple-touch-icon.png +0 -0
  50. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/assets/images/favicon-16x16.png +0 -0
  51. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/assets/images/favicon-32x32.png +0 -0
  52. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/assets/images/favicon.ico +0 -0
  53. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/assets/images/og-agentirc.png +0 -0
  54. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/assets/images/og-culture.png +0 -0
  55. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/__init__.py +0 -0
  56. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/__main__.py +0 -0
  57. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/agentirc/CLAUDE.md +0 -0
  58. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/agentirc/__init__.py +0 -0
  59. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/agentirc/__main__.py +0 -0
  60. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/agentirc/channel.py +0 -0
  61. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/agentirc/docs/agentirc-architecture.md +0 -0
  62. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/agentirc/docs/agentirc-features.md +0 -0
  63. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/agentirc/docs/agentirc-skill.md +0 -0
  64. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/agentirc/docs/agentirc.md +0 -0
  65. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/agentirc/events.py +0 -0
  66. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/agentirc/history_store.py +0 -0
  67. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/agentirc/remote_client.py +0 -0
  68. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/agentirc/room_store.py +0 -0
  69. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/agentirc/rooms_util.py +0 -0
  70. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/agentirc/server_link.py +0 -0
  71. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/agentirc/skill.py +0 -0
  72. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/agentirc/skills/__init__.py +0 -0
  73. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/agentirc/skills/history.py +0 -0
  74. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/agentirc/skills/icon.py +0 -0
  75. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/agentirc/skills/rooms.py +0 -0
  76. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/agentirc/skills/threads.py +0 -0
  77. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/agentirc/thread_store.py +0 -0
  78. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/aio.py +0 -0
  79. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/bots/__init__.py +0 -0
  80. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/bots/bot.py +0 -0
  81. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/bots/bot_manager.py +0 -0
  82. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/bots/config.py +0 -0
  83. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/bots/filter_dsl.py +0 -0
  84. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/bots/http_listener.py +0 -0
  85. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/bots/system/__init__.py +0 -0
  86. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/bots/system/welcome/__init__.py +0 -0
  87. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/bots/system/welcome/bot.yaml +0 -0
  88. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/bots/system/welcome/handler.py +0 -0
  89. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/bots/template_engine.py +0 -0
  90. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/bots/virtual_client.py +0 -0
  91. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/cli/__init__.py +0 -0
  92. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/cli/_passthrough.py +0 -0
  93. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/cli/afi.py +0 -0
  94. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/cli/agent.py +0 -0
  95. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/cli/bot.py +0 -0
  96. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/cli/channel.py +0 -0
  97. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/cli/devex.py +0 -0
  98. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/cli/introspect.py +0 -0
  99. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/cli/mesh.py +0 -0
  100. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/cli/server.py +0 -0
  101. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/cli/shared/__init__.py +0 -0
  102. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/cli/shared/constants.py +0 -0
  103. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/cli/shared/display.py +0 -0
  104. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/cli/shared/formatting.py +0 -0
  105. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/cli/shared/ipc.py +0 -0
  106. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/cli/shared/mesh.py +0 -0
  107. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/cli/shared/process.py +0 -0
  108. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/cli/skills.py +0 -0
  109. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/__init__.py +0 -0
  110. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/acp/__init__.py +0 -0
  111. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/acp/agent_runner.py +0 -0
  112. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/acp/config.py +0 -0
  113. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/acp/culture.yaml +0 -0
  114. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/acp/daemon.py +0 -0
  115. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/acp/ipc.py +0 -0
  116. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/acp/irc_transport.py +0 -0
  117. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/acp/message_buffer.py +0 -0
  118. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/acp/skill/SKILL.md +0 -0
  119. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/acp/skill/__init__.py +0 -0
  120. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/acp/skill/irc_client.py +0 -0
  121. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/acp/socket_server.py +0 -0
  122. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/acp/supervisor.py +0 -0
  123. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/acp/webhook.py +0 -0
  124. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/claude/__init__.py +0 -0
  125. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/claude/__main__.py +0 -0
  126. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/claude/agent_runner.py +0 -0
  127. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/claude/config.py +0 -0
  128. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/claude/culture.yaml +0 -0
  129. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/claude/daemon.py +0 -0
  130. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/claude/ipc.py +0 -0
  131. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/claude/irc_transport.py +0 -0
  132. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/claude/message_buffer.py +0 -0
  133. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/claude/skill/SKILL.md +0 -0
  134. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/claude/skill/__init__.py +0 -0
  135. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/claude/skill/irc_client.py +0 -0
  136. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/claude/socket_server.py +0 -0
  137. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/claude/supervisor.py +0 -0
  138. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/claude/webhook.py +0 -0
  139. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/codex/__init__.py +0 -0
  140. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/codex/agent_runner.py +0 -0
  141. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/codex/config.py +0 -0
  142. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/codex/culture.yaml +0 -0
  143. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/codex/daemon.py +0 -0
  144. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/codex/ipc.py +0 -0
  145. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/codex/irc_transport.py +0 -0
  146. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/codex/message_buffer.py +0 -0
  147. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/codex/skill/SKILL.md +0 -0
  148. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/codex/skill/__init__.py +0 -0
  149. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/codex/skill/irc_client.py +0 -0
  150. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/codex/socket_server.py +0 -0
  151. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/codex/supervisor.py +0 -0
  152. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/codex/webhook.py +0 -0
  153. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/copilot/__init__.py +0 -0
  154. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/copilot/agent_runner.py +0 -0
  155. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/copilot/config.py +0 -0
  156. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/copilot/culture.yaml +0 -0
  157. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/copilot/daemon.py +0 -0
  158. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/copilot/ipc.py +0 -0
  159. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/copilot/irc_transport.py +0 -0
  160. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/copilot/message_buffer.py +0 -0
  161. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/copilot/skill/SKILL.md +0 -0
  162. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/copilot/skill/__init__.py +0 -0
  163. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/copilot/skill/irc_client.py +0 -0
  164. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/copilot/socket_server.py +0 -0
  165. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/copilot/supervisor.py +0 -0
  166. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/clients/copilot/webhook.py +0 -0
  167. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/config.py +0 -0
  168. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/console/__init__.py +0 -0
  169. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/console/app.py +0 -0
  170. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/console/client.py +0 -0
  171. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/console/commands.py +0 -0
  172. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/console/status.py +0 -0
  173. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/console/widgets/__init__.py +0 -0
  174. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/console/widgets/chat.py +0 -0
  175. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/console/widgets/info_panel.py +0 -0
  176. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/console/widgets/sidebar.py +0 -0
  177. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/constants.py +0 -0
  178. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/credentials.py +0 -0
  179. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/formatting.py +0 -0
  180. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/learn_prompt.py +0 -0
  181. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/mesh_config.py +0 -0
  182. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/observer.py +0 -0
  183. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/overview/__init__.py +0 -0
  184. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/overview/collector.py +0 -0
  185. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/overview/model.py +0 -0
  186. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/overview/renderer_text.py +0 -0
  187. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/overview/renderer_web.py +0 -0
  188. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/overview/web/style.css +0 -0
  189. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/persistence.py +0 -0
  190. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/pidfile.py +0 -0
  191. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/protocol/__init__.py +0 -0
  192. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/protocol/commands.py +0 -0
  193. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/protocol/extensions/events.md +0 -0
  194. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/protocol/extensions/federation.md +0 -0
  195. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/protocol/extensions/history.md +0 -0
  196. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/protocol/extensions/icons.md +0 -0
  197. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/protocol/extensions/rooms.md +0 -0
  198. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/protocol/extensions/tags.md +0 -0
  199. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/protocol/extensions/threads.md +0 -0
  200. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/protocol/extensions/tracing.md +0 -0
  201. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/protocol/message.py +0 -0
  202. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/protocol/protocol-index.md +0 -0
  203. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/protocol/replies.py +0 -0
  204. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/skills/culture/SKILL.md +0 -0
  205. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/telemetry/context.py +0 -0
  206. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/culture/telemetry/tracing.py +0 -0
  207. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/README.md +0 -0
  208. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/agentirc/architecture-overview.md +0 -0
  209. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/agentirc/bots.md +0 -0
  210. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/agentirc/events.md +0 -0
  211. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/agentirc/index.md +0 -0
  212. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/agentirc/otelcol-template.yaml +0 -0
  213. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/agentirc/why-agentirc.md +0 -0
  214. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/culture/agent-lifecycle.md +0 -0
  215. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/culture/choose-a-harness.md +0 -0
  216. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/culture/features.md +0 -0
  217. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/culture/index.md +0 -0
  218. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/culture/mental-model.md +0 -0
  219. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/culture/operate.md +0 -0
  220. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/culture/patterns.md +0 -0
  221. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/culture/quickstart.md +0 -0
  222. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/culture/reflective-development.md +0 -0
  223. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/culture/vision-patterns-index.md +0 -0
  224. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/culture/vision.md +0 -0
  225. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/culture/what-is-culture.md +0 -0
  226. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/reference/architecture/agent-harness-spec.md +0 -0
  227. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/reference/architecture/index.md +0 -0
  228. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/reference/architecture/layers.md +0 -0
  229. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/reference/architecture/subsites.md +0 -0
  230. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/reference/architecture/threads.md +0 -0
  231. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/reference/cli/afi.md +0 -0
  232. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/reference/cli/commands.md +0 -0
  233. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/reference/cli/devex.md +0 -0
  234. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/reference/cli/index.md +0 -0
  235. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/reference/console.md +0 -0
  236. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/reference/harnesses/acp.md +0 -0
  237. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/reference/harnesses/claude.md +0 -0
  238. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/reference/harnesses/codex.md +0 -0
  239. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/reference/harnesses/copilot.md +0 -0
  240. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/reference/harnesses/index.md +0 -0
  241. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/reference/index.md +0 -0
  242. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/reference/server/architecture.md +0 -0
  243. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/reference/server/config.md +0 -0
  244. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/reference/server/deployment.md +0 -0
  245. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/reference/server/index.md +0 -0
  246. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/reference/server/security.md +0 -0
  247. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/resources/github-copilot-sdk-instructions.md +0 -0
  248. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/resources/positioning.md +0 -0
  249. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/shared/concepts/federation.md +0 -0
  250. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/shared/concepts/harnesses.md +0 -0
  251. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/shared/concepts/humans-and-agents.md +0 -0
  252. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/shared/concepts/index.md +0 -0
  253. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/shared/concepts/persistence.md +0 -0
  254. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/shared/concepts/rooms.md +0 -0
  255. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/shared/demos/magic-demo.md +0 -0
  256. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/shared/guides/first-session.md +0 -0
  257. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/shared/guides/index.md +0 -0
  258. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/shared/guides/join-as-human.md +0 -0
  259. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/shared/guides/local-setup.md +0 -0
  260. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/shared/guides/multi-machine.md +0 -0
  261. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/shared/use-cases/01-pair-programming.md +0 -0
  262. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/shared/use-cases/02-code-review-ensemble.md +0 -0
  263. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/shared/use-cases/03-cross-server-delegation.md +0 -0
  264. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/shared/use-cases/04-knowledge-propagation.md +0 -0
  265. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/shared/use-cases/05-the-observer.md +0 -0
  266. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/shared/use-cases/06-cross-server-ops.md +0 -0
  267. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/shared/use-cases/07-supervisor-intervention.md +0 -0
  268. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/shared/use-cases/08-apps-as-agents.md +0 -0
  269. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/shared/use-cases/09-research-swarm.md +0 -0
  270. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/shared/use-cases/10-agent-lifecycle.md +0 -0
  271. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/shared/use-cases-index.md +0 -0
  272. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/plans/2026-03-19-layer1-core-irc.md +0 -0
  273. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/plans/2026-03-21-layer5-agent-harness.md +0 -0
  274. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/plans/2026-03-30-overview.md +0 -0
  275. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/plans/2026-03-30-rooms-management.md +0 -0
  276. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/plans/2026-04-02-conversation-threads.md +0 -0
  277. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/plans/2026-04-02-ops-tooling.md +0 -0
  278. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/plans/2026-04-04-culture-rename.md +0 -0
  279. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/plans/2026-04-05-docs-speak-culture.md +0 -0
  280. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/plans/2026-04-06-console-chat.md +0 -0
  281. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/plans/2026-04-09-decentralized-agent-config.md +0 -0
  282. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/plans/2026-04-12-console-enhancements.md +0 -0
  283. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/plans/2026-04-15-mesh-events.md +0 -0
  284. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/plans/2026-04-18-culture-dev-positioning.md +0 -0
  285. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/plans/2026-04-22-agex-integration.md +0 -0
  286. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/plans/2026-04-24-otel-foundation.md +0 -0
  287. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/plans/2026-04-25-otel-federation.md +0 -0
  288. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/plans/2026-04-26-otel-metrics.md +0 -0
  289. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/specs/2026-03-19-agentirc-design.md +0 -0
  290. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/specs/2026-03-21-layer5-agent-harness-design.md +0 -0
  291. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/specs/2026-03-30-overview-design.md +0 -0
  292. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/specs/2026-03-30-rooms-management-design.md +0 -0
  293. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/specs/2026-04-02-conversation-threads-design.md +0 -0
  294. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/specs/2026-04-02-ops-tooling-design.md +0 -0
  295. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/specs/2026-04-03-bots-webhooks-design.md +0 -0
  296. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/specs/2026-04-04-culture-rename-design.md +0 -0
  297. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/specs/2026-04-05-docs-speak-culture-design.md +0 -0
  298. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/specs/2026-04-05-lifecycle-reframe-design.md +0 -0
  299. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/specs/2026-04-06-cli-reorganization-design.md +0 -0
  300. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/specs/2026-04-06-console-chat-design.md +0 -0
  301. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/specs/2026-04-07-entity-archiving-design.md +0 -0
  302. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/specs/2026-04-07-reflective-development-reframe-design.md +0 -0
  303. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/specs/2026-04-08-reflective-development-deepening-design.md +0 -0
  304. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/specs/2026-04-09-decentralized-agent-config-design.md +0 -0
  305. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/specs/2026-04-12-console-enhancements-design.md +0 -0
  306. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/specs/2026-04-15-mesh-events-design.md +0 -0
  307. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/specs/2026-04-17-sites-repositioning-design.md +0 -0
  308. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/specs/2026-04-18-culture-dev-positioning-design.md +0 -0
  309. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/specs/2026-04-22-agex-integration-design.md +0 -0
  310. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/docs/superpowers/specs/2026-04-24-otel-observability-design.md +0 -0
  311. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/favicon.ico +0 -0
  312. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/packages/agent-harness/README.md +0 -0
  313. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/packages/agent-harness/config.py +0 -0
  314. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/packages/agent-harness/culture.yaml +0 -0
  315. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/packages/agent-harness/daemon.py +0 -0
  316. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/packages/agent-harness/ipc.py +0 -0
  317. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/packages/agent-harness/irc_transport.py +0 -0
  318. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/packages/agent-harness/message_buffer.py +0 -0
  319. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/packages/agent-harness/skill/SKILL.md +0 -0
  320. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/packages/agent-harness/skill/irc_client.py +0 -0
  321. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/packages/agent-harness/socket_server.py +0 -0
  322. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/packages/agent-harness/webhook.py +0 -0
  323. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/plugins/claude-code/.claude-plugin/plugin.json +0 -0
  324. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/plugins/claude-code/skills/culture/SKILL.md +0 -0
  325. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/plugins/claude-code/skills/irc/SKILL.md +0 -0
  326. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/plugins/codex/skills/culture-irc/SKILL.md +0 -0
  327. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/robots.txt +0 -0
  328. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/sitemap-agentirc.html +0 -0
  329. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/sitemap-main.html +0 -0
  330. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/sitemap.html +0 -0
  331. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/sonar-project.properties +0 -0
  332. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/__init__.py +0 -0
  333. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/telemetry/__init__.py +0 -0
  334. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/telemetry/_fakes.py +0 -0
  335. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/telemetry/_metrics_helpers.py +0 -0
  336. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/telemetry/test_config.py +0 -0
  337. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/telemetry/test_config_load.py +0 -0
  338. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/telemetry/test_context.py +0 -0
  339. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/telemetry/test_dispatch_span.py +0 -0
  340. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/telemetry/test_emit_event_span.py +0 -0
  341. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/telemetry/test_federation_propagation.py +0 -0
  342. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/telemetry/test_metrics_clients.py +0 -0
  343. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/telemetry/test_metrics_events.py +0 -0
  344. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/telemetry/test_metrics_init.py +0 -0
  345. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/telemetry/test_metrics_irc.py +0 -0
  346. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/telemetry/test_metrics_s2s.py +0 -0
  347. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/telemetry/test_metrics_trace_inbound.py +0 -0
  348. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/telemetry/test_outbound_inject.py +0 -0
  349. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/telemetry/test_parse_error.py +0 -0
  350. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/telemetry/test_privmsg_span.py +0 -0
  351. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/telemetry/test_s2s_dispatch_span.py +0 -0
  352. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/telemetry/test_s2s_relay_span.py +0 -0
  353. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/telemetry/test_s2s_session_span.py +0 -0
  354. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/telemetry/test_server_init.py +0 -0
  355. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/telemetry/test_server_link_inject.py +0 -0
  356. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/telemetry/test_session_span.py +0 -0
  357. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/telemetry/test_tracing.py +0 -0
  358. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_acp_daemon.py +0 -0
  359. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_agent_runner.py +0 -0
  360. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_archive.py +0 -0
  361. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_bot.py +0 -0
  362. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_bot_config.py +0 -0
  363. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_bot_config_fires_event_toplevel.py +0 -0
  364. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_bot_manager.py +0 -0
  365. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_bots_integration.py +0 -0
  366. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_channel.py +0 -0
  367. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_channel_cli.py +0 -0
  368. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_cli_afi.py +0 -0
  369. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_cli_devex.py +0 -0
  370. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_cli_introspect.py +0 -0
  371. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_cli_passthrough.py +0 -0
  372. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_codex_daemon.py +0 -0
  373. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_connection.py +0 -0
  374. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_console_chat_markdown.py +0 -0
  375. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_console_client.py +0 -0
  376. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_console_commands.py +0 -0
  377. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_console_connection.py +0 -0
  378. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_console_fixes_224_227.py +0 -0
  379. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_console_icons.py +0 -0
  380. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_console_integration.py +0 -0
  381. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_console_status.py +0 -0
  382. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_copilot_daemon.py +0 -0
  383. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_credentials.py +0 -0
  384. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_culture_config.py +0 -0
  385. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_daemon.py +0 -0
  386. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_daemon_config.py +0 -0
  387. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_daemon_ipc.py +0 -0
  388. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_discovery.py +0 -0
  389. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_display.py +0 -0
  390. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_events_basic.py +0 -0
  391. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_events_bot_chain.py +0 -0
  392. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_events_bot_trigger.py +0 -0
  393. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_events_cap_fallback.py +0 -0
  394. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_events_catalog.py +0 -0
  395. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_events_federation.py +0 -0
  396. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_events_history.py +0 -0
  397. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_events_lifecycle.py +0 -0
  398. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_events_reserved_nick.py +0 -0
  399. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_federation.py +0 -0
  400. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_filter_dsl.py +0 -0
  401. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_history.py +0 -0
  402. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_http_listener.py +0 -0
  403. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_integration_layer5.py +0 -0
  404. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_ipc.py +0 -0
  405. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_irc_transport.py +0 -0
  406. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_irc_transport_tags.py +0 -0
  407. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_learn_prompt.py +0 -0
  408. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_link_reconnect.py +0 -0
  409. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_manifest_config.py +0 -0
  410. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_mention_alias.py +0 -0
  411. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_mention_target_cleanup.py +0 -0
  412. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_mention_warning.py +0 -0
  413. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_mentions.py +0 -0
  414. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_mesh_config.py +0 -0
  415. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_mesh_readiness.py +0 -0
  416. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_message.py +0 -0
  417. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_message_buffer.py +0 -0
  418. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_message_tags.py +0 -0
  419. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_messaging.py +0 -0
  420. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_migrate_cli.py +0 -0
  421. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_modes.py +0 -0
  422. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_overview_cli.py +0 -0
  423. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_overview_collector.py +0 -0
  424. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_overview_model.py +0 -0
  425. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_overview_renderer.py +0 -0
  426. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_overview_web.py +0 -0
  427. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_persistence.py +0 -0
  428. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_persistence_timeout.py +0 -0
  429. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_pidfile.py +0 -0
  430. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_poll_loop.py +0 -0
  431. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_register_cli.py +0 -0
  432. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_room_persistence.py +0 -0
  433. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_rooms.py +0 -0
  434. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_rooms_federation.py +0 -0
  435. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_rooms_integration.py +0 -0
  436. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_server_icon_skill.py +0 -0
  437. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_setup_update_cli.py +0 -0
  438. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_skill_client.py +0 -0
  439. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_skill_docs.py +0 -0
  440. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_skills.py +0 -0
  441. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_socket_server.py +0 -0
  442. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_supervisor.py +0 -0
  443. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_template_engine.py +0 -0
  444. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_thread_buffer.py +0 -0
  445. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_threads.py +0 -0
  446. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_virtual_client.py +0 -0
  447. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_wait_for_port.py +0 -0
  448. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_webhook.py +0 -0
  449. {agentirc_cli-8.4.0 → agentirc_cli-8.5.0}/tests/test_welcome_bot.py +0 -0
@@ -4,6 +4,21 @@ 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.5.0] - 2026-04-25
8
+
9
+ ### Added
10
+
11
+ - `culture/telemetry/audit.py` — `AuditSink` with bounded `asyncio.Queue` + dedicated writer task + daily/size rotation + `0600`/`0700` perms.
12
+ - Public `culture.telemetry.AuditSink`, `init_audit`, `build_audit_record`, `utc_iso_timestamp`.
13
+ - `TelemetryConfig.audit_enabled` (default `True`), `audit_dir`, `audit_max_file_bytes`, `audit_rotate_utc_midnight`, `audit_queue_depth` — independent of `telemetry.enabled` (audit fires even with OTEL off).
14
+ - `culture/protocol/extensions/audit.md` — JSONL record schema as a stable contract.
15
+ - `docs/agentirc/audit.md` — operator guide.
16
+ - Audit metrics extend the Plan-3 `MetricsRegistry`: `culture.audit.writes` (Counter, labels `outcome=ok|error`) and `culture.audit.queue_depth` (UpDownCounter).
17
+ - `IRCd.__init__` creates the sink; `IRCd.start()` awaits `sink.start()`; `IRCd.stop()` awaits `sink.shutdown()` so SERVER_WAKE / SERVER_SLEEP both land in the JSONL.
18
+ - `IRCd.emit_event` submits one record per event after the `irc.event.emit` span; `trace_id` / `span_id` captured inside the span for cross-pillar joins.
19
+ - `Client._process_buffer` submits `PARSE_ERROR` records for malformed inbound lines.
20
+ - Federation audit: federated `message` events arrive on the receiver with `origin=federated`, `peer=<peer_name>`. Federated lifecycle events (JOIN/PART/QUIT) are deferred — see #296.
21
+
7
22
  ## [8.4.0] - 2026-04-25
8
23
 
9
24
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentirc-cli
3
- Version: 8.4.0
3
+ Version: 8.5.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
@@ -17,6 +17,7 @@ from culture.aio import maybe_await
17
17
  from culture.constants import SYSTEM_USER_PREFIX
18
18
  from culture.protocol import replies
19
19
  from culture.protocol.message import Message
20
+ from culture.telemetry.audit import utc_iso_timestamp as _utc_iso_timestamp
20
21
  from culture.telemetry.context import TRACEPARENT_TAG as _TP_TAG_NAME
21
22
  from culture.telemetry.context import (
22
23
  context_from_traceparent,
@@ -148,6 +149,7 @@ class Client:
148
149
  "error": type(exc).__name__,
149
150
  },
150
151
  )
152
+ self._submit_parse_error_audit(line, exc)
151
153
  continue
152
154
  # Record received bytes + message size for every successfully-parsed
153
155
  # line. +2 accounts for the \r\n that was stripped during line-split.
@@ -160,6 +162,49 @@ class Client:
160
162
  await self._dispatch(msg)
161
163
  return buffer
162
164
 
165
+ def _submit_parse_error_audit(self, line: str, exc: BaseException) -> None:
166
+ """Build and submit a PARSE_ERROR audit record for a malformed inbound line.
167
+
168
+ The record cannot go through build_audit_record (which expects an Event);
169
+ PARSE_ERROR is a synthetic event_type with no Event object behind it.
170
+ """
171
+ # Capture trace/span ids from the active span (the
172
+ # `irc.client.process_buffer` we're inside of).
173
+ span = _otel_trace.get_current_span()
174
+ ctx = span.get_span_context()
175
+ trace_id_hex = format(ctx.trace_id, "032x") if ctx.is_valid else ""
176
+ span_id_hex = format(ctx.span_id, "016x") if ctx.is_valid else ""
177
+
178
+ peer_info = self.writer.get_extra_info("peername")
179
+ remote_addr = f"{peer_info[0]}:{peer_info[1]}" if peer_info else ""
180
+
181
+ tags: dict[str, str] = {}
182
+ tp = current_traceparent()
183
+ if tp:
184
+ tags["culture.dev/traceparent"] = tp
185
+
186
+ record = {
187
+ "ts": _utc_iso_timestamp(time.time()),
188
+ "server": self.server.config.name,
189
+ "event_type": "PARSE_ERROR",
190
+ "origin": "local",
191
+ "peer": "",
192
+ "trace_id": trace_id_hex,
193
+ "span_id": span_id_hex,
194
+ "actor": {
195
+ "nick": self.nick or "",
196
+ "kind": "human",
197
+ "remote_addr": remote_addr,
198
+ },
199
+ "target": {"kind": "", "name": ""},
200
+ "payload": {
201
+ "line_preview": line[:64],
202
+ "error": type(exc).__name__,
203
+ },
204
+ "tags": tags,
205
+ }
206
+ self.server.audit.submit(record)
207
+
163
208
  async def handle(self, initial_msg: str | None = None) -> None:
164
209
  peer_info = self.writer.get_extra_info("peername")
165
210
  remote_addr = f"{peer_info[0]}:{peer_info[1]}" if peer_info else ""
@@ -26,6 +26,13 @@ class TelemetryConfig:
26
26
  traces_sampler: str = "parentbased_always_on"
27
27
  metrics_enabled: bool = True
28
28
  metrics_export_interval_ms: int = 10000
29
+ # Audit JSONL sink (Plan 4). Independent of `enabled` — audit fires
30
+ # even when telemetry is off so admins always have the trail.
31
+ audit_enabled: bool = True
32
+ audit_dir: str = "~/.culture/audit"
33
+ audit_max_file_bytes: int = 256 * 1024 * 1024 # 256 MiB
34
+ audit_rotate_utc_midnight: bool = True
35
+ audit_queue_depth: int = 10000
29
36
 
30
37
 
31
38
  @dataclass
@@ -23,12 +23,14 @@ from culture.constants import (
23
23
  SYSTEM_USER_PREFIX,
24
24
  )
25
25
  from culture.protocol.message import Message
26
+ from culture.telemetry import build_audit_record, current_traceparent
26
27
 
27
28
  logger = logging.getLogger(__name__)
28
29
 
29
30
  # Span/metric attribute keys defined once so a future rename has one edit point.
30
31
  _ATTR_EVENT_TYPE = "event.type"
31
32
 
33
+
32
34
  if TYPE_CHECKING:
33
35
  from culture.agentirc.client import Client
34
36
  from culture.agentirc.remote_client import RemoteClient
@@ -39,11 +41,12 @@ class IRCd:
39
41
  """The culture IRC server."""
40
42
 
41
43
  def __init__(self, config: ServerConfig):
42
- from culture.telemetry import init_metrics, init_telemetry
44
+ from culture.telemetry import init_audit, init_metrics, init_telemetry
43
45
 
44
46
  self.config = config
45
47
  self.tracer = init_telemetry(config)
46
48
  self.metrics = init_metrics(config)
49
+ self.audit = init_audit(config, self.metrics)
47
50
  self.clients: dict[str, Client | VirtualClient] = {} # nick -> Client
48
51
  self.channels: dict[str, Channel] = {} # name -> Channel
49
52
  self.skills: list[Skill] = []
@@ -74,6 +77,8 @@ class IRCd:
74
77
  logger.info("Bootstrapping system identity...")
75
78
  self._bootstrap_system_identity()
76
79
 
80
+ await self.audit.start()
81
+
77
82
  await self.emit_event(
78
83
  Event(
79
84
  type=EventType.SERVER_WAKE,
@@ -223,14 +228,25 @@ class IRCd:
223
228
  self.metrics.events_emitted.add(1, {_ATTR_EVENT_TYPE: event_type_str, "origin": origin_str})
224
229
  render_started = time.perf_counter()
225
230
 
231
+ trace_id_hex = ""
232
+ span_id_hex = ""
233
+ tp: str | None = None
234
+
226
235
  # Per-call get_tracer: the `tracing_exporter` test fixture swaps the
227
236
  # global provider between tests; a cached Tracer would bind to the
228
237
  # first test's provider and stop delivering to later ones.
229
238
  with _otel_trace.get_tracer("culture.agentirc").start_as_current_span(
230
239
  "irc.event.emit", attributes=attrs
231
- ):
240
+ ) as span:
232
241
  seq = self.next_seq()
233
242
  self._event_log.append((seq, event))
243
+ ctx = span.get_span_context()
244
+ if ctx.is_valid:
245
+ trace_id_hex = format(ctx.trace_id, "032x")
246
+ span_id_hex = format(ctx.span_id, "016x")
247
+ # Capture traceparent inside the span so trace_flags reflect
248
+ # the actual sampling decision for this span, not a hardcoded -01.
249
+ tp = current_traceparent()
234
250
  await self._run_skill_hooks(event)
235
251
  if not origin_tag:
236
252
  await self._relay_to_peers(event)
@@ -240,6 +256,22 @@ class IRCd:
240
256
  render_ms = (time.perf_counter() - render_started) * 1000.0
241
257
  self.metrics.events_render_duration.record(render_ms, {_ATTR_EVENT_TYPE: event_type_str})
242
258
 
259
+ # Audit submit happens after the span exits so it doesn't sit inside
260
+ # the irc.event.emit span (would skew render duration). The trace_id/
261
+ # span_id captured inside the span point back at it for cross-pillar
262
+ # joins.
263
+ tags: dict[str, str] = {"culture.dev/traceparent": tp} if tp else {}
264
+ self.audit.submit(
265
+ build_audit_record(
266
+ server_name=self.config.name,
267
+ event=event,
268
+ origin_tag=origin_tag,
269
+ trace_id=trace_id_hex,
270
+ span_id=span_id_hex,
271
+ extra_tags=tags,
272
+ )
273
+ )
274
+
243
275
  _NO_SURFACE_TYPES = NO_SURFACE_EVENT_TYPES
244
276
 
245
277
  @staticmethod
@@ -395,6 +427,7 @@ class IRCd:
395
427
  if self._server:
396
428
  self._server.close()
397
429
  await self._server.wait_closed()
430
+ await self.audit.shutdown()
398
431
  finally:
399
432
  self._stopped.set()
400
433
 
@@ -0,0 +1,109 @@
1
+ # Extension: Audit JSONL Sink
2
+
3
+ The audit log is a durable, file-based JSON-Lines (`.jsonl`) trail of every event the server
4
+ emits. It is **separate from OTEL traces / metrics / logs** — audit lands directly on local disk
5
+ and never depends on a running collector. Admin-only "who said what to whom, when, via what path."
6
+
7
+ ## File Layout
8
+
9
+ - **Path:** `<audit_dir>/<server_name>-<YYYY-MM-DD>.jsonl` where `<audit_dir>` defaults to
10
+ `~/.culture/audit/` (configurable via `telemetry.audit_dir`). The date is **UTC**.
11
+ - **File mode:** `0600` (owner read/write only).
12
+ - **Directory mode:** `0700` (owner only). Created on demand if missing; existing dir mode is
13
+ left as-is.
14
+ - **Rotation suffix:** when the daily file hits the size cap, the next file gets `.1`, then
15
+ `.2`, … same date. New day starts a fresh file with no suffix.
16
+
17
+ Example for server `spark` on 2026-04-27 with two size-cap rotations:
18
+
19
+ ```text
20
+ ~/.culture/audit/spark-2026-04-27.jsonl # first 256 MiB
21
+ ~/.culture/audit/spark-2026-04-27.1.jsonl # next 256 MiB
22
+ ~/.culture/audit/spark-2026-04-27.2.jsonl # current
23
+ ```
24
+
25
+ ## Record Schema
26
+
27
+ Each line in the file is a single JSON object. Lines never wrap. Keys are lowercase with `_`
28
+ separators. Order is canonicalized at write time (stable across writes). Future schema additions
29
+ are additive only — consumers must tolerate unknown keys.
30
+
31
+ Keys within each record are alphabetically sorted (the writer uses
32
+ `json.dumps(..., sort_keys=True)`). Consumers SHOULD NOT rely on
33
+ insertion order; future producers may emit keys in any order.
34
+
35
+ | Field | Type | Required | Description |
36
+ |-------|------|----------|-------------|
37
+ | `ts` | string | yes | ISO 8601 UTC timestamp with microsecond precision and trailing `Z` (e.g. `2026-04-27T14:32:05.123456Z`). |
38
+ | `server` | string | yes | Server name from `ServerConfig.name`. |
39
+ | `event_type` | string | yes | `EventType.value` (e.g. `message`, `user.join`, `room.create`) or the special string `PARSE_ERROR` for malformed inbound lines. |
40
+ | `origin` | string | yes | `local` if the event originated on this server; `federated` if it arrived via a peer link. |
41
+ | `peer` | string | yes | Peer server name when `origin=federated`; empty string `""` otherwise. |
42
+ | `trace_id` | string | yes | OTEL trace-id (32 hex chars) of the active span at submit time, or `""` if no span. |
43
+ | `span_id` | string | yes | OTEL span-id (16 hex chars) of the active span, or `""`. |
44
+ | `actor` | object | yes | `{nick, kind, remote_addr}` describing who/what produced the event. |
45
+ | `actor.nick` | string | yes | The nick from the event (`event.nick`), or `""`. |
46
+ | `actor.kind` | string | yes | One of `human`, `bot`, `harness`. v1 always emits `human` — Plans 5/6 refine. |
47
+ | `actor.remote_addr` | string | yes | `"<ip>:<port>"` if known (PARSE_ERROR via Client; empty for server-internal sites). |
48
+ | `target` | object | yes | `{kind, name}` describing what the event affected. |
49
+ | `target.kind` | string | yes | `channel` (event.channel set), `nick` (DM target), or `""` for global events. |
50
+ | `target.name` | string | yes | The channel or nick; `""` for global. |
51
+ | `payload` | object | yes | `event.data` with all underscore-prefix keys (`_origin`, etc.) stripped. May include `nick` / `channel` defaulted from `event.nick`/`event.channel`. |
52
+ | `tags` | object | yes | IRCv3-style tag bag. v1 emits at most `culture.dev/traceparent` derived from the active span; empty `{}` if no span. |
53
+
54
+ ## Rotation
55
+
56
+ Rotation fires when **either** condition is met, checked at the top of every record write:
57
+
58
+ 1. The current UTC date differs from `current_date` (daily roll, controlled by
59
+ `telemetry.audit_rotate_utc_midnight`).
60
+ 2. The current file size + the about-to-be-written record size exceeds
61
+ `telemetry.audit_max_file_bytes` (default 256 MiB).
62
+
63
+ The new file is opened with `O_WRONLY | O_APPEND | O_CREAT` mode `0600`. Writes use a single
64
+ `os.write` per record so partial-line interleaving is impossible.
65
+
66
+ A record larger than `audit_max_file_bytes` is still written — the cap is a soft
67
+ ceiling for accumulated bytes, not a hard reject. The oversized record lands in
68
+ its own freshly-rotated file, and the next record triggers another rotation.
69
+
70
+ ## Durability
71
+
72
+ Records flow through a bounded `asyncio.Queue` (depth `telemetry.audit_queue_depth`, default
73
+ 10000). A dedicated writer task drains the queue and writes each record. On queue overflow, the
74
+ record is **dropped** and `culture.audit.writes{outcome=error}` increments. A stderr warning is
75
+ logged.
76
+
77
+ This is a deliberate trade-off: dropping records is preferable to blocking `IRCd.emit_event`. A
78
+ real-world audit gap is rare and recoverable; a blocked event loop is catastrophic.
79
+
80
+ No `fsync` per record — writes hit the page cache and rely on the OS to flush. A hard crash can
81
+ lose the in-flight record.
82
+
83
+ ## Retention
84
+
85
+ Files are not auto-pruned in v1. Operators prune manually:
86
+
87
+ ```bash
88
+ find ~/.culture/audit -name 'spark-*.jsonl*' -mtime +30 -delete
89
+ ```
90
+
91
+ A future `audit-prune` CLI is TODO.
92
+
93
+ ## Compat
94
+
95
+ The schema is a stable contract:
96
+
97
+ - New fields can be added in future versions; old consumers must tolerate unknown keys.
98
+ - Existing keys keep their type and semantics across versions.
99
+ - If a future version needs a breaking change, a top-level `schema_version` integer will be
100
+ added and bumped — until that exists, treat the schema as version 1.
101
+
102
+ ## Example
103
+
104
+ PRIVMSG from `alpha-alice` (a federated client on the `alpha` peer) to channel `#general` on
105
+ the local server `spark`:
106
+
107
+ ```json
108
+ {"ts":"2026-04-27T14:32:05.123456Z","server":"spark","event_type":"message","origin":"federated","peer":"alpha","trace_id":"4bf92f3577b34da6a3ce929d0e0e4736","span_id":"00f067aa0ba902b7","actor":{"nick":"alpha-alice","kind":"human","remote_addr":""},"target":{"kind":"channel","name":"#general"},"payload":{"text":"hi","nick":"alpha-alice","channel":"#general"},"tags":{"culture.dev/traceparent":"00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01"}}
109
+ ```
@@ -3,6 +3,7 @@
3
3
  Public surface re-exported here; call sites import from `culture.telemetry`.
4
4
  """
5
5
 
6
+ from culture.telemetry.audit import AuditSink, build_audit_record, init_audit, utc_iso_timestamp
6
7
  from culture.telemetry.context import (
7
8
  TRACEPARENT_TAG,
8
9
  TRACESTATE_TAG,
@@ -16,14 +17,18 @@ from culture.telemetry.metrics import MetricsRegistry, init_metrics
16
17
  from culture.telemetry.tracing import init_telemetry
17
18
 
18
19
  __all__ = [
20
+ "AuditSink",
19
21
  "ExtractResult",
20
22
  "MetricsRegistry",
21
23
  "TRACEPARENT_TAG",
22
24
  "TRACESTATE_TAG",
25
+ "build_audit_record",
23
26
  "context_from_traceparent",
24
27
  "current_traceparent",
25
28
  "extract_traceparent_from_tags",
29
+ "init_audit",
26
30
  "init_metrics",
27
31
  "init_telemetry",
28
32
  "inject_traceparent",
33
+ "utc_iso_timestamp",
29
34
  ]