agentirc-cli 8.6.0__tar.gz → 8.7.1__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.
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/CHANGELOG.md +25 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/PKG-INFO +2 -1
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/bots/bot.py +24 -13
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/bots/bot_manager.py +53 -24
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/bots/http_listener.py +35 -1
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/cli/channel.py +36 -1
- agentirc_cli-8.7.1/culture/cli/shared/constants.py +54 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/acp/daemon.py +2 -1
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/acp/skill/irc_client.py +2 -2
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/claude/daemon.py +2 -1
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/claude/skill/irc_client.py +2 -2
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/codex/daemon.py +2 -1
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/codex/skill/irc_client.py +2 -2
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/copilot/daemon.py +2 -1
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/copilot/skill/irc_client.py +2 -2
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/overview/collector.py +2 -2
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/telemetry/metrics.py +13 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/agentirc/harness-telemetry.md +1 -1
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/agentirc/telemetry.md +39 -3
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/reference/architecture/agent-harness-spec.md +12 -1
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/reference/cli/index.md +13 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/specs/2026-04-24-otel-observability-design.md +1 -1
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/packages/agent-harness/daemon.py +2 -1
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/packages/agent-harness/skill/irc_client.py +2 -2
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/pyproject.toml +2 -1
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/telemetry/_metrics_helpers.py +9 -0
- agentirc_cli-8.7.1/tests/telemetry/conftest.py +33 -0
- agentirc_cli-8.7.1/tests/telemetry/test_bot_event_dispatch_span.py +138 -0
- agentirc_cli-8.7.1/tests/telemetry/test_bot_run_span.py +91 -0
- agentirc_cli-8.7.1/tests/telemetry/test_metrics_bots.py +127 -0
- agentirc_cli-8.7.1/tests/telemetry/test_metrics_webhook.py +148 -0
- agentirc_cli-8.7.1/tests/telemetry/test_webhook_http_span.py +45 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_channel_cli.py +78 -1
- agentirc_cli-8.7.1/tests/test_constants.py +86 -0
- agentirc_cli-8.7.1/tests/test_socket_path_convergence.py +153 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/uv.lock +107 -1
- agentirc_cli-8.6.0/culture/cli/shared/constants.py +0 -43
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/.claude/agents/doc-test-alignment.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/.claude/skills/pr-review/SKILL.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/.claude/skills/run-tests/SKILL.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/.claude/skills/run-tests/scripts/test.sh +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/.flake8 +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/.github/workflows/docs-check.yml +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/.github/workflows/publish.yml +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/.github/workflows/security-checks.yml +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/.github/workflows/tests.yml +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/.gitignore +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/.markdownlint-cli2.yaml +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/.pr_agent.toml +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/.pre-commit-config.yaml +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/.pylintrc +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/CLAUDE.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/Gemfile +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/Gemfile.lock +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/LICENSE +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/README.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/SECURITY.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/_config.base.yml +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/_config.culture.yml +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/_data/sites.yml +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/_includes/head_custom.html +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/_sass/color_schemes/anthropic.scss +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/_sass/color_schemes/dark-terminal.scss +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/_sass/custom/custom.scss +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/assets/images/IMG_3183.png +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/assets/images/apple-touch-icon.png +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/assets/images/favicon-16x16.png +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/assets/images/favicon-32x32.png +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/assets/images/favicon.ico +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/assets/images/og-agentirc.png +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/assets/images/og-culture.png +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/__init__.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/__main__.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/agentirc/CLAUDE.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/agentirc/__init__.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/agentirc/__main__.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/agentirc/channel.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/agentirc/client.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/agentirc/config.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/agentirc/docs/agentirc-architecture.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/agentirc/docs/agentirc-features.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/agentirc/docs/agentirc-skill.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/agentirc/docs/agentirc.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/agentirc/events.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/agentirc/history_store.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/agentirc/ircd.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/agentirc/remote_client.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/agentirc/room_store.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/agentirc/rooms_util.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/agentirc/server_link.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/agentirc/skill.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/agentirc/skills/__init__.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/agentirc/skills/history.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/agentirc/skills/icon.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/agentirc/skills/rooms.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/agentirc/skills/threads.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/agentirc/thread_store.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/aio.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/bots/__init__.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/bots/config.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/bots/filter_dsl.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/bots/system/__init__.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/bots/system/welcome/__init__.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/bots/system/welcome/bot.yaml +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/bots/system/welcome/handler.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/bots/template_engine.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/bots/virtual_client.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/cli/__init__.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/cli/_passthrough.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/cli/afi.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/cli/agent.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/cli/bot.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/cli/devex.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/cli/introspect.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/cli/mesh.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/cli/server.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/cli/shared/__init__.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/cli/shared/display.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/cli/shared/formatting.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/cli/shared/ipc.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/cli/shared/mesh.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/cli/shared/process.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/cli/skills.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/__init__.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/acp/__init__.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/acp/agent_runner.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/acp/config.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/acp/culture.yaml +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/acp/ipc.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/acp/irc_transport.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/acp/message_buffer.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/acp/skill/SKILL.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/acp/skill/__init__.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/acp/socket_server.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/acp/supervisor.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/acp/telemetry.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/acp/webhook.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/claude/__init__.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/claude/__main__.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/claude/agent_runner.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/claude/config.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/claude/culture.yaml +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/claude/ipc.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/claude/irc_transport.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/claude/message_buffer.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/claude/skill/SKILL.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/claude/skill/__init__.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/claude/socket_server.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/claude/supervisor.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/claude/telemetry.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/claude/webhook.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/codex/__init__.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/codex/agent_runner.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/codex/config.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/codex/culture.yaml +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/codex/ipc.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/codex/irc_transport.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/codex/message_buffer.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/codex/skill/SKILL.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/codex/skill/__init__.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/codex/socket_server.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/codex/supervisor.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/codex/telemetry.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/codex/webhook.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/copilot/__init__.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/copilot/agent_runner.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/copilot/config.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/copilot/culture.yaml +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/copilot/ipc.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/copilot/irc_transport.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/copilot/message_buffer.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/copilot/skill/SKILL.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/copilot/skill/__init__.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/copilot/socket_server.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/copilot/supervisor.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/copilot/telemetry.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/clients/copilot/webhook.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/config.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/console/__init__.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/console/app.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/console/client.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/console/commands.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/console/status.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/console/widgets/__init__.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/console/widgets/chat.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/console/widgets/info_panel.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/console/widgets/sidebar.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/constants.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/credentials.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/formatting.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/learn_prompt.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/mesh_config.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/observer.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/overview/__init__.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/overview/model.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/overview/renderer_text.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/overview/renderer_web.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/overview/web/style.css +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/persistence.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/pidfile.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/protocol/__init__.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/protocol/commands.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/protocol/extensions/audit.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/protocol/extensions/events.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/protocol/extensions/federation.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/protocol/extensions/history.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/protocol/extensions/icons.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/protocol/extensions/rooms.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/protocol/extensions/tags.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/protocol/extensions/threads.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/protocol/extensions/tracing.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/protocol/message.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/protocol/protocol-index.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/protocol/replies.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/skills/culture/SKILL.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/telemetry/__init__.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/telemetry/audit.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/telemetry/context.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/culture/telemetry/tracing.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/README.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/agentirc/architecture-overview.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/agentirc/audit.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/agentirc/bots.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/agentirc/events.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/agentirc/index.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/agentirc/otelcol-template.yaml +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/agentirc/why-agentirc.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/culture/agent-lifecycle.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/culture/choose-a-harness.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/culture/features.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/culture/index.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/culture/mental-model.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/culture/operate.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/culture/patterns.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/culture/quickstart.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/culture/reflective-development.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/culture/vision-patterns-index.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/culture/vision.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/culture/what-is-culture.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/reference/architecture/index.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/reference/architecture/layers.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/reference/architecture/subsites.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/reference/architecture/threads.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/reference/cli/afi.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/reference/cli/commands.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/reference/cli/devex.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/reference/console.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/reference/harnesses/acp.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/reference/harnesses/claude.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/reference/harnesses/codex.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/reference/harnesses/copilot.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/reference/harnesses/index.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/reference/index.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/reference/server/architecture.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/reference/server/config.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/reference/server/deployment.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/reference/server/index.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/reference/server/security.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/resources/github-copilot-sdk-instructions.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/resources/positioning.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/shared/concepts/federation.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/shared/concepts/harnesses.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/shared/concepts/humans-and-agents.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/shared/concepts/index.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/shared/concepts/persistence.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/shared/concepts/rooms.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/shared/demos/magic-demo.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/shared/guides/first-session.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/shared/guides/index.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/shared/guides/join-as-human.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/shared/guides/local-setup.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/shared/guides/multi-machine.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/shared/use-cases/01-pair-programming.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/shared/use-cases/02-code-review-ensemble.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/shared/use-cases/03-cross-server-delegation.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/shared/use-cases/04-knowledge-propagation.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/shared/use-cases/05-the-observer.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/shared/use-cases/06-cross-server-ops.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/shared/use-cases/07-supervisor-intervention.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/shared/use-cases/08-apps-as-agents.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/shared/use-cases/09-research-swarm.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/shared/use-cases/10-agent-lifecycle.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/shared/use-cases-index.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/plans/2026-03-19-layer1-core-irc.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/plans/2026-03-21-layer5-agent-harness.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/plans/2026-03-30-overview.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/plans/2026-03-30-rooms-management.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/plans/2026-04-02-conversation-threads.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/plans/2026-04-02-ops-tooling.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/plans/2026-04-04-culture-rename.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/plans/2026-04-05-docs-speak-culture.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/plans/2026-04-06-console-chat.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/plans/2026-04-09-decentralized-agent-config.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/plans/2026-04-12-console-enhancements.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/plans/2026-04-15-mesh-events.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/plans/2026-04-18-culture-dev-positioning.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/plans/2026-04-22-agex-integration.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/plans/2026-04-24-otel-foundation.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/plans/2026-04-25-otel-federation.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/plans/2026-04-26-otel-metrics.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/plans/2026-04-27-otel-audit.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/plans/2026-04-28-otel-harness.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/specs/2026-03-19-agentirc-design.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/specs/2026-03-21-layer5-agent-harness-design.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/specs/2026-03-30-overview-design.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/specs/2026-03-30-rooms-management-design.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/specs/2026-04-02-conversation-threads-design.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/specs/2026-04-02-ops-tooling-design.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/specs/2026-04-03-bots-webhooks-design.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/specs/2026-04-04-culture-rename-design.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/specs/2026-04-05-docs-speak-culture-design.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/specs/2026-04-05-lifecycle-reframe-design.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/specs/2026-04-06-cli-reorganization-design.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/specs/2026-04-06-console-chat-design.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/specs/2026-04-07-entity-archiving-design.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/specs/2026-04-07-reflective-development-reframe-design.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/specs/2026-04-08-reflective-development-deepening-design.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/specs/2026-04-09-decentralized-agent-config-design.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/specs/2026-04-12-console-enhancements-design.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/specs/2026-04-15-mesh-events-design.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/specs/2026-04-17-sites-repositioning-design.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/specs/2026-04-18-culture-dev-positioning-design.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/docs/superpowers/specs/2026-04-22-agex-integration-design.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/favicon.ico +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/packages/agent-harness/README.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/packages/agent-harness/config.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/packages/agent-harness/culture.yaml +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/packages/agent-harness/ipc.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/packages/agent-harness/irc_transport.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/packages/agent-harness/message_buffer.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/packages/agent-harness/skill/SKILL.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/packages/agent-harness/socket_server.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/packages/agent-harness/telemetry.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/packages/agent-harness/webhook.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/plugins/claude-code/.claude-plugin/plugin.json +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/plugins/claude-code/skills/culture/SKILL.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/plugins/claude-code/skills/irc/SKILL.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/plugins/codex/skills/culture-irc/SKILL.md +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/robots.txt +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/sitemap-agentirc.html +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/sitemap-main.html +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/sitemap.html +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/sonar-project.properties +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/__init__.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/conftest.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/harness/__init__.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/harness/conftest.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/harness/test_agent_runner_acp.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/harness/test_agent_runner_claude.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/harness/test_agent_runner_codex.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/harness/test_agent_runner_copilot.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/harness/test_all_backends_parity.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/harness/test_daemon_telemetry.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/harness/test_irc_transport_propagation.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/harness/test_record_llm_call.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/harness/test_telemetry_module.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/telemetry/__init__.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/telemetry/_fakes.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/telemetry/test_audit_emit.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/telemetry/test_audit_federation.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/telemetry/test_audit_lifecycle.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/telemetry/test_audit_module.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/telemetry/test_audit_parse_error.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/telemetry/test_config.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/telemetry/test_config_load.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/telemetry/test_context.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/telemetry/test_dispatch_span.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/telemetry/test_emit_event_span.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/telemetry/test_federation_propagation.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/telemetry/test_metrics_clients.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/telemetry/test_metrics_events.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/telemetry/test_metrics_init.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/telemetry/test_metrics_irc.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/telemetry/test_metrics_s2s.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/telemetry/test_metrics_trace_inbound.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/telemetry/test_outbound_inject.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/telemetry/test_parse_error.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/telemetry/test_privmsg_span.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/telemetry/test_s2s_dispatch_span.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/telemetry/test_s2s_relay_span.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/telemetry/test_s2s_session_span.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/telemetry/test_server_init.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/telemetry/test_server_link_inject.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/telemetry/test_session_span.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/telemetry/test_tracing.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_acp_daemon.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_agent_runner.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_archive.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_bot.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_bot_config.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_bot_config_fires_event_toplevel.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_bot_manager.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_bots_integration.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_channel.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_cli_afi.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_cli_devex.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_cli_introspect.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_cli_passthrough.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_codex_daemon.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_connection.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_console_chat_markdown.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_console_client.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_console_commands.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_console_connection.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_console_fixes_224_227.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_console_icons.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_console_integration.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_console_status.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_copilot_daemon.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_credentials.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_culture_config.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_daemon.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_daemon_config.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_daemon_ipc.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_discovery.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_display.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_events_basic.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_events_bot_chain.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_events_bot_trigger.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_events_cap_fallback.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_events_catalog.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_events_federation.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_events_history.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_events_lifecycle.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_events_reserved_nick.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_federation.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_filter_dsl.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_history.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_http_listener.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_integration_layer5.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_ipc.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_irc_transport.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_irc_transport_tags.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_learn_prompt.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_link_reconnect.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_manifest_config.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_mention_alias.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_mention_target_cleanup.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_mention_warning.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_mentions.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_mesh_config.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_mesh_readiness.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_message.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_message_buffer.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_message_tags.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_messaging.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_migrate_cli.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_modes.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_overview_cli.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_overview_collector.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_overview_model.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_overview_renderer.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_overview_web.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_persistence.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_persistence_timeout.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_pidfile.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_poll_loop.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_register_cli.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_room_persistence.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_rooms.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_rooms_federation.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_rooms_integration.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_server_icon_skill.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_setup_update_cli.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_skill_client.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_skill_docs.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_skills.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_socket_server.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_supervisor.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_template_engine.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_thread_buffer.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_threads.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_virtual_client.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_wait_for_port.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_webhook.py +0 -0
- {agentirc_cli-8.6.0 → agentirc_cli-8.7.1}/tests/test_welcome_bot.py +0 -0
|
@@ -4,6 +4,31 @@ 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.1] - 2026-04-27
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- `tests/test_socket_path_convergence.py`: parametric regression test asserting all 8 daemon+skill resolvers agree with the CLI's `agent_socket_path()` for both `XDG_RUNTIME_DIR` set and unset.
|
|
12
|
+
- `tests/test_constants.py`: unit tests pinning `culture_runtime_dir()` contract (env precedence, `~/.culture/run/` fallback, mode 0700).
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- `culture channel {message,list,read}`: when `CULTURE_NICK` is set but the daemon IPC is unreachable or rejects the request, the CLI now prints a stderr warning naming the nick, the socket path, and the GitHub issue tracker before falling back to the peek-nick observer. The fallback itself is preserved for human use (no `CULTURE_NICK`).
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- Converged all socket-path resolvers (4 backend daemons, 4 skill irc_clients, overview collector, harness package reference impl) on `culture_runtime_dir()` so the CLI and daemon agree on the IPC socket path when `XDG_RUNTIME_DIR` is unset (macOS default). Previously the daemon listened on `/tmp/culture-<nick>.sock` while the CLI looked in `~/.culture/run/`, causing `culture channel message` to silently fall back to an anonymous `_peek<random>` nick (#302, regression of #203).
|
|
21
|
+
|
|
22
|
+
## [8.7.0] - 2026-04-26
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- 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.
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
|
|
30
|
+
- docs/agentirc/telemetry.md updated with the 8.7.0 section; harness-telemetry.md cross-link updated.
|
|
31
|
+
|
|
7
32
|
## [8.6.0] - 2026-04-26
|
|
8
33
|
|
|
9
34
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentirc-cli
|
|
3
|
-
Version: 8.
|
|
3
|
+
Version: 8.7.1
|
|
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
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
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
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
|
116
|
-
|
|
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
|
-
|
|
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
|
|
|
@@ -24,11 +24,43 @@ def _valid_nick(nick: str) -> bool:
|
|
|
24
24
|
return len(parts) == 2 and all(parts)
|
|
25
25
|
|
|
26
26
|
|
|
27
|
+
_ISSUE_TRACKER_URL = "https://github.com/agentculture/culture/issues"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _warn_observer_fallback(operation: str) -> None:
|
|
31
|
+
"""Warn on stderr when an observer-fallback command silently went anonymous.
|
|
32
|
+
|
|
33
|
+
Called only by the three commands that do fall back to the observer
|
|
34
|
+
connection (`message`, `list`, `read`). `topic` and the `_require_ipc`
|
|
35
|
+
commands exit on failure instead, so this helper is not used there —
|
|
36
|
+
a misleading "falling back" notice would contradict the actual error.
|
|
37
|
+
|
|
38
|
+
Issue #302: a daemon/CLI socket-path mismatch on macOS hid behind the
|
|
39
|
+
silent peek fallback for two releases. The warning names the issue
|
|
40
|
+
tracker so the next reproducer takes seconds to file.
|
|
41
|
+
"""
|
|
42
|
+
nick = os.environ.get("CULTURE_NICK")
|
|
43
|
+
if not nick or not _valid_nick(nick):
|
|
44
|
+
return # Human use without CULTURE_NICK — observer is the intended path.
|
|
45
|
+
sock = agent_socket_path(nick)
|
|
46
|
+
print(
|
|
47
|
+
f"Warning: agent daemon IPC for {nick} failed ({sock}).\n"
|
|
48
|
+
f" Falling back to observer connection — `{operation}` will not run\n"
|
|
49
|
+
f" through the agent daemon and the action will not appear under {nick}.\n"
|
|
50
|
+
f" Verify the daemon is running: culture agent status {nick}\n"
|
|
51
|
+
f" If it is running, this is a bug. Please open an issue:\n"
|
|
52
|
+
f" {_ISSUE_TRACKER_URL}",
|
|
53
|
+
file=sys.stderr,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
|
|
27
57
|
def _try_ipc(msg_type: str, **kwargs) -> dict | None:
|
|
28
58
|
"""Try to route a command through the agent daemon's IPC socket.
|
|
29
59
|
|
|
30
60
|
Returns the response dict if CULTURE_NICK is set and the daemon is
|
|
31
|
-
reachable, otherwise None (caller should fall back to observer
|
|
61
|
+
reachable, otherwise None (caller should fall back to observer or
|
|
62
|
+
surface its own error — see `_warn_observer_fallback` for the
|
|
63
|
+
observer-fallback path).
|
|
32
64
|
"""
|
|
33
65
|
nick = os.environ.get("CULTURE_NICK")
|
|
34
66
|
if not nick or not _valid_nick(nick):
|
|
@@ -169,6 +201,7 @@ def _cmd_list(args: argparse.Namespace) -> None:
|
|
|
169
201
|
print(f" {ch}")
|
|
170
202
|
return
|
|
171
203
|
|
|
204
|
+
_warn_observer_fallback("channel list")
|
|
172
205
|
observer = get_observer(args.config)
|
|
173
206
|
channels = asyncio.run(observer.list_channels())
|
|
174
207
|
|
|
@@ -199,6 +232,7 @@ def _cmd_read(args: argparse.Namespace) -> None:
|
|
|
199
232
|
print(f"<{nick}> {text}")
|
|
200
233
|
return
|
|
201
234
|
|
|
235
|
+
_warn_observer_fallback("channel read")
|
|
202
236
|
observer = get_observer(args.config)
|
|
203
237
|
messages = asyncio.run(observer.read_channel(channel, limit=args.limit))
|
|
204
238
|
|
|
@@ -267,6 +301,7 @@ def _cmd_message(args: argparse.Namespace) -> None:
|
|
|
267
301
|
print(f"Sent to {target}")
|
|
268
302
|
return
|
|
269
303
|
|
|
304
|
+
_warn_observer_fallback("channel message")
|
|
270
305
|
observer = get_observer(args.config)
|
|
271
306
|
asyncio.run(observer.send_message(target, text))
|
|
272
307
|
print(f"Sent to {target}")
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""Shared constants for culture CLI modules."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import stat
|
|
5
|
+
|
|
6
|
+
from culture.bots.config import BOT_CONFIG_FILE # noqa: F401
|
|
7
|
+
|
|
8
|
+
DEFAULT_CONFIG = os.path.expanduser("~/.culture/server.yaml")
|
|
9
|
+
LOG_DIR = os.path.expanduser("~/.culture/logs")
|
|
10
|
+
|
|
11
|
+
_CONFIG_HELP = "Config file path"
|
|
12
|
+
_SERVER_NAME_HELP = "Server name"
|
|
13
|
+
_BOT_NAME_HELP = "Bot name"
|
|
14
|
+
|
|
15
|
+
DEFAULT_CHANNEL = "#general"
|
|
16
|
+
NO_AGENTS_MSG = "No agents configured"
|
|
17
|
+
CULTURE_DIR = ".culture"
|
|
18
|
+
AGENTS_YAML = "agents.yaml"
|
|
19
|
+
|
|
20
|
+
DEFAULT_SERVER_CONFIG = os.path.expanduser("~/.culture/server.yaml")
|
|
21
|
+
LEGACY_CONFIG = os.path.expanduser("~/.culture/agents.yaml")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def culture_runtime_dir() -> str:
|
|
25
|
+
"""Return a user-private directory for culture daemon sockets.
|
|
26
|
+
|
|
27
|
+
Resolution order:
|
|
28
|
+
|
|
29
|
+
1. ``$XDG_RUNTIME_DIR`` when set (Linux/systemd default — already
|
|
30
|
+
user-private at ``/run/user/<uid>``).
|
|
31
|
+
2. ``~/.culture/run/`` otherwise (typical macOS path), created mode
|
|
32
|
+
0700 if missing and re-tightened to 0700 on every call so a
|
|
33
|
+
hand-created or pre-existing dir cannot leak sockets.
|
|
34
|
+
|
|
35
|
+
Raises ``RuntimeError`` when neither ``XDG_RUNTIME_DIR`` nor a
|
|
36
|
+
resolvable home directory is available — silently writing a literal
|
|
37
|
+
``~/.culture/run`` directory in CWD would surprise callers and the
|
|
38
|
+
daemons (which now route through this resolver) would fail at
|
|
39
|
+
socket-bind time anyway.
|
|
40
|
+
"""
|
|
41
|
+
xdg = os.environ.get("XDG_RUNTIME_DIR")
|
|
42
|
+
if xdg:
|
|
43
|
+
return xdg
|
|
44
|
+
home = os.path.expanduser("~")
|
|
45
|
+
if not home or home == "~" or not os.path.isabs(home):
|
|
46
|
+
raise RuntimeError(
|
|
47
|
+
"culture_runtime_dir(): cannot resolve a home directory "
|
|
48
|
+
"(os.path.expanduser('~') returned %r). Set $HOME or "
|
|
49
|
+
"$XDG_RUNTIME_DIR before running culture commands." % home
|
|
50
|
+
)
|
|
51
|
+
fallback = os.path.join(home, ".culture", "run")
|
|
52
|
+
os.makedirs(fallback, mode=0o700, exist_ok=True)
|
|
53
|
+
os.chmod(fallback, stat.S_IRWXU)
|
|
54
|
+
return fallback
|
|
@@ -18,6 +18,7 @@ import time
|
|
|
18
18
|
from collections import deque
|
|
19
19
|
|
|
20
20
|
from culture.aio import maybe_await
|
|
21
|
+
from culture.cli.shared.constants import culture_runtime_dir
|
|
21
22
|
from culture.clients.acp.agent_runner import ACPAgentRunner
|
|
22
23
|
from culture.clients.acp.config import AgentConfig, DaemonConfig
|
|
23
24
|
from culture.clients.acp.ipc import make_response
|
|
@@ -62,7 +63,7 @@ class ACPDaemon:
|
|
|
62
63
|
self.skip_agent = skip_agent
|
|
63
64
|
|
|
64
65
|
self._socket_path = os.path.join(
|
|
65
|
-
socket_dir or
|
|
66
|
+
socket_dir or culture_runtime_dir(),
|
|
66
67
|
f"culture-{agent.nick}.sock",
|
|
67
68
|
)
|
|
68
69
|
|
|
@@ -16,6 +16,7 @@ import os
|
|
|
16
16
|
import sys
|
|
17
17
|
from typing import Any
|
|
18
18
|
|
|
19
|
+
from culture.cli.shared.constants import culture_runtime_dir
|
|
19
20
|
from culture.clients.acp.ipc import (
|
|
20
21
|
MSG_TYPE_RESPONSE,
|
|
21
22
|
MSG_TYPE_WHISPER,
|
|
@@ -192,8 +193,7 @@ def _sock_path_from_env() -> str:
|
|
|
192
193
|
if not nick:
|
|
193
194
|
print("ERROR: CULTURE_NICK environment variable is not set", file=sys.stderr)
|
|
194
195
|
sys.exit(1)
|
|
195
|
-
|
|
196
|
-
return os.path.join(runtime_dir, f"culture-{nick}.sock")
|
|
196
|
+
return os.path.join(culture_runtime_dir(), f"culture-{nick}.sock")
|
|
197
197
|
|
|
198
198
|
|
|
199
199
|
def _parse_ask_timeout(remaining: list[str]) -> tuple[int, list[str]]:
|
|
@@ -8,6 +8,7 @@ import re
|
|
|
8
8
|
import time
|
|
9
9
|
|
|
10
10
|
from culture.aio import maybe_await
|
|
11
|
+
from culture.cli.shared.constants import culture_runtime_dir
|
|
11
12
|
from culture.clients.claude.agent_runner import AgentRunner
|
|
12
13
|
from culture.clients.claude.config import AgentConfig, DaemonConfig
|
|
13
14
|
from culture.clients.claude.ipc import make_response
|
|
@@ -51,7 +52,7 @@ class AgentDaemon:
|
|
|
51
52
|
self.skip_claude = skip_claude
|
|
52
53
|
|
|
53
54
|
self._socket_path = os.path.join(
|
|
54
|
-
socket_dir or
|
|
55
|
+
socket_dir or culture_runtime_dir(),
|
|
55
56
|
f"culture-{agent.nick}.sock",
|
|
56
57
|
)
|
|
57
58
|
|
|
@@ -16,6 +16,7 @@ import os
|
|
|
16
16
|
import sys
|
|
17
17
|
from typing import Any
|
|
18
18
|
|
|
19
|
+
from culture.cli.shared.constants import culture_runtime_dir
|
|
19
20
|
from culture.clients.claude.ipc import (
|
|
20
21
|
MSG_TYPE_RESPONSE,
|
|
21
22
|
MSG_TYPE_WHISPER,
|
|
@@ -189,8 +190,7 @@ def _sock_path_from_env() -> str:
|
|
|
189
190
|
if not nick:
|
|
190
191
|
print("ERROR: CULTURE_NICK environment variable is not set", file=sys.stderr)
|
|
191
192
|
sys.exit(1)
|
|
192
|
-
|
|
193
|
-
return os.path.join(runtime_dir, f"culture-{nick}.sock")
|
|
193
|
+
return os.path.join(culture_runtime_dir(), f"culture-{nick}.sock")
|
|
194
194
|
|
|
195
195
|
|
|
196
196
|
def _parse_ask_timeout(remaining: list[str]) -> tuple[int, list[str]]:
|
|
@@ -15,6 +15,7 @@ import time
|
|
|
15
15
|
from collections import deque
|
|
16
16
|
|
|
17
17
|
from culture.aio import maybe_await
|
|
18
|
+
from culture.cli.shared.constants import culture_runtime_dir
|
|
18
19
|
from culture.clients.codex.agent_runner import CodexAgentRunner
|
|
19
20
|
from culture.clients.codex.config import AgentConfig, DaemonConfig
|
|
20
21
|
from culture.clients.codex.ipc import make_response
|
|
@@ -66,7 +67,7 @@ class CodexDaemon:
|
|
|
66
67
|
self.skip_codex = skip_codex
|
|
67
68
|
|
|
68
69
|
self._socket_path = os.path.join(
|
|
69
|
-
socket_dir or
|
|
70
|
+
socket_dir or culture_runtime_dir(),
|
|
70
71
|
f"culture-{agent.nick}.sock",
|
|
71
72
|
)
|
|
72
73
|
|
|
@@ -16,6 +16,7 @@ import os
|
|
|
16
16
|
import sys
|
|
17
17
|
from typing import Any
|
|
18
18
|
|
|
19
|
+
from culture.cli.shared.constants import culture_runtime_dir
|
|
19
20
|
from culture.clients.codex.ipc import (
|
|
20
21
|
MSG_TYPE_RESPONSE,
|
|
21
22
|
MSG_TYPE_WHISPER,
|
|
@@ -189,8 +190,7 @@ def _sock_path_from_env() -> str:
|
|
|
189
190
|
if not nick:
|
|
190
191
|
print("ERROR: CULTURE_NICK environment variable is not set", file=sys.stderr)
|
|
191
192
|
sys.exit(1)
|
|
192
|
-
|
|
193
|
-
return os.path.join(runtime_dir, f"culture-{nick}.sock")
|
|
193
|
+
return os.path.join(culture_runtime_dir(), f"culture-{nick}.sock")
|
|
194
194
|
|
|
195
195
|
|
|
196
196
|
def _parse_ask_timeout(remaining: list[str]) -> tuple[int, list[str]]:
|
|
@@ -15,6 +15,7 @@ import time
|
|
|
15
15
|
from collections import deque
|
|
16
16
|
|
|
17
17
|
from culture.aio import maybe_await
|
|
18
|
+
from culture.cli.shared.constants import culture_runtime_dir
|
|
18
19
|
from culture.clients.copilot.agent_runner import CopilotAgentRunner
|
|
19
20
|
from culture.clients.copilot.config import AgentConfig, DaemonConfig
|
|
20
21
|
from culture.clients.copilot.ipc import make_response
|
|
@@ -59,7 +60,7 @@ class CopilotDaemon:
|
|
|
59
60
|
self.skip_copilot = skip_copilot
|
|
60
61
|
|
|
61
62
|
self._socket_path = os.path.join(
|
|
62
|
-
socket_dir or
|
|
63
|
+
socket_dir or culture_runtime_dir(),
|
|
63
64
|
f"culture-{agent.nick}.sock",
|
|
64
65
|
)
|
|
65
66
|
|
|
@@ -16,6 +16,7 @@ import os
|
|
|
16
16
|
import sys
|
|
17
17
|
from typing import Any
|
|
18
18
|
|
|
19
|
+
from culture.cli.shared.constants import culture_runtime_dir
|
|
19
20
|
from culture.clients.copilot.ipc import (
|
|
20
21
|
MSG_TYPE_RESPONSE,
|
|
21
22
|
MSG_TYPE_WHISPER,
|
|
@@ -192,8 +193,7 @@ def _sock_path_from_env() -> str:
|
|
|
192
193
|
if not nick:
|
|
193
194
|
print("ERROR: CULTURE_NICK environment variable is not set", file=sys.stderr)
|
|
194
195
|
sys.exit(1)
|
|
195
|
-
|
|
196
|
-
return os.path.join(runtime_dir, f"culture-{nick}.sock")
|
|
196
|
+
return os.path.join(culture_runtime_dir(), f"culture-{nick}.sock")
|
|
197
197
|
|
|
198
198
|
|
|
199
199
|
def _parse_ask_timeout(remaining: list[str]) -> tuple[int, list[str]]:
|
|
@@ -7,6 +7,7 @@ import glob
|
|
|
7
7
|
import os
|
|
8
8
|
|
|
9
9
|
from culture.bots.config import BOT_CONFIG_FILE
|
|
10
|
+
from culture.cli.shared.constants import culture_runtime_dir
|
|
10
11
|
from culture.protocol.message import Message as IRCMessage
|
|
11
12
|
|
|
12
13
|
from .model import Agent, BotInfo, MeshState, Message, Room
|
|
@@ -428,8 +429,7 @@ async def _enrich_via_ipc(agents: dict[str, Agent], server_name: str) -> None:
|
|
|
428
429
|
"""Enrich local agents with daemon IPC status data."""
|
|
429
430
|
from culture.clients.claude.ipc import decode_message, encode_message, make_request
|
|
430
431
|
|
|
431
|
-
|
|
432
|
-
socket_pattern = os.path.join(runtime_dir, "culture-*.sock")
|
|
432
|
+
socket_pattern = os.path.join(culture_runtime_dir(), "culture-*.sock")
|
|
433
433
|
|
|
434
434
|
for sock_path in glob.glob(socket_pattern):
|
|
435
435
|
# Extract nick from socket filename: culture-<nick>.sock
|
|
@@ -63,6 +63,9 @@ class MetricsRegistry:
|
|
|
63
63
|
# Audit (Plan 4)
|
|
64
64
|
audit_writes: Counter
|
|
65
65
|
audit_queue_depth: UpDownCounter
|
|
66
|
+
# Bots (Plan 7)
|
|
67
|
+
bot_invocations: Counter
|
|
68
|
+
bot_webhook_duration: Histogram
|
|
66
69
|
|
|
67
70
|
|
|
68
71
|
def reset_for_tests() -> None:
|
|
@@ -168,6 +171,16 @@ def _build_registry(meter: Meter) -> MetricsRegistry:
|
|
|
168
171
|
"culture.audit.queue_depth",
|
|
169
172
|
description="Audit queue depth (records waiting to flush to disk)",
|
|
170
173
|
),
|
|
174
|
+
# Bots (Plan 7)
|
|
175
|
+
bot_invocations=meter.create_counter(
|
|
176
|
+
"culture.bot.invocations",
|
|
177
|
+
description="Bot dispatch invocations by bot, event.type, outcome=success|error",
|
|
178
|
+
),
|
|
179
|
+
bot_webhook_duration=meter.create_histogram(
|
|
180
|
+
"culture.bot.webhook.duration",
|
|
181
|
+
unit="s",
|
|
182
|
+
description="Webhook request handler duration by bot and status_class=2xx|3xx|4xx|5xx",
|
|
183
|
+
),
|
|
171
184
|
)
|
|
172
185
|
|
|
173
186
|
|
|
@@ -230,7 +230,7 @@ corresponding key is present in `usage` with an `int` value.
|
|
|
230
230
|
|
|
231
231
|
## What's not in 8.6.0
|
|
232
232
|
|
|
233
|
-
- **Bot-side OTEL instrumentation** — Plan
|
|
233
|
+
- **Bot-side OTEL instrumentation** — shipped in 8.7.0 (Plan 7). See [`telemetry.md`](telemetry.html#what-you-get-in-870).
|
|
234
234
|
- **Tracestate injection** — server-parity-deferred. Both server-side
|
|
235
235
|
`client.py` / `server_link.py` and the harness currently pass `tracestate=None`
|
|
236
236
|
when injecting. A future plan will add `current_tracestate()` to
|
|
@@ -9,7 +9,7 @@ nav_order: 90
|
|
|
9
9
|
|
|
10
10
|
Culture ships with first-class OpenTelemetry support: traces for every IRC command and event, W3C trace context carried across federation via a new IRCv3 tag, and a local collector pattern that keeps Culture's surface small.
|
|
11
11
|
|
|
12
|
-
This page covers the **Foundation + Server Tracing** release (culture 8.2.0), **Federation Trace-Context Relay** (culture 8.3.0), the **Metrics Pillar** (culture 8.4.0), the **Audit JSONL Sink** (culture 8.5.0),
|
|
12
|
+
This page covers the **Foundation + Server Tracing** release (culture 8.2.0), **Federation Trace-Context Relay** (culture 8.3.0), the **Metrics Pillar** (culture 8.4.0), the **Audit JSONL Sink** (culture 8.5.0), **Harness-side OTEL** (culture 8.6.0), and **Bot Instrumentation** (culture 8.7.0).
|
|
13
13
|
|
|
14
14
|
## What you get in 8.2.0
|
|
15
15
|
|
|
@@ -189,11 +189,47 @@ For full configuration details, the per-backend `service.name` table, the
|
|
|
189
189
|
end-to-end test recipe, and a list of what's deferred, see the operator guide at
|
|
190
190
|
[`docs/agentirc/harness-telemetry.html`](harness-telemetry.html).
|
|
191
191
|
|
|
192
|
-
## What
|
|
192
|
+
## What you get in 8.7.0
|
|
193
|
+
|
|
194
|
+
Bot instrumentation lands. Event-triggered dispatch and webhook-triggered dispatch each get their own span tree, both stitched into the same trace as the upstream client/server activity that triggered them.
|
|
195
|
+
|
|
196
|
+
Event-trigger path:
|
|
197
|
+
|
|
198
|
+
```text
|
|
199
|
+
irc.command.PRIVMSG (or any event-emitting verb)
|
|
200
|
+
└── irc.event.emit
|
|
201
|
+
└── bot.event.dispatch (one per matched bot)
|
|
202
|
+
└── bot.run (Bot.handle body)
|
|
203
|
+
└── irc.privmsg.deliver.channel | .dm
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Webhook path:
|
|
207
|
+
|
|
208
|
+
```text
|
|
209
|
+
HTTP POST /<bot_name> (auto-instrumented inbound span)
|
|
210
|
+
└── bot.run (Bot.handle body)
|
|
211
|
+
└── irc.privmsg.deliver.*
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
New spans:
|
|
215
|
+
|
|
216
|
+
- `bot.event.dispatch` — one per matched bot inside `BotManager.on_event`. Attributes: `bot.name`, `event.type`. Status `ERROR` if `Bot.handle` raises.
|
|
217
|
+
- `bot.run` — wraps `Bot.handle` for both event and webhook paths. Attributes: `bot.name`, optional `bot.run.empty_message=True` if the rendered message is empty.
|
|
218
|
+
|
|
219
|
+
The webhook HTTP server is auto-instrumented via [`opentelemetry-instrumentation-aiohttp-server`](https://pypi.org/project/opentelemetry-instrumentation-aiohttp-server/). Each request produces an inbound HTTP server span (verb + path + status code) that becomes the parent of `bot.run`. If the caller sends a `traceparent` header, the request joins their existing trace.
|
|
220
|
+
|
|
221
|
+
New metrics:
|
|
222
|
+
|
|
223
|
+
- `culture.bot.invocations` — Counter. Labels: `bot`, `event.type`, `outcome=success|error`. Increments only after the bot has matched the filter and been started — filter rejections and startup failures are logged but not counted.
|
|
224
|
+
- `culture.bot.webhook.duration` — Histogram, `s`. Labels: `bot`, `status_class=2xx|3xx|4xx|5xx`. Recorded by a per-request middleware on the webhook listener. `bot=_unrouted` is used for `/health` and other non-bot paths so the histogram never silently mis-attributes.
|
|
225
|
+
|
|
226
|
+
Bots add no new wire protocol surface. Trace context flows in via the existing IRCv3 `culture.dev/traceparent` tag for events and via the standard W3C `traceparent` HTTP header for webhooks.
|
|
227
|
+
|
|
228
|
+
## What's not in 8.7.0
|
|
193
229
|
|
|
194
230
|
The design spec at `docs/superpowers/specs/2026-04-24-otel-observability-design.md` covers the full three-pillar scope. These pieces remain deferred:
|
|
195
231
|
|
|
196
|
-
-
|
|
232
|
+
- Outbound webhook delivery instrumentation (`opentelemetry-instrumentation-aiohttp-client`) — bots currently make no outbound HTTP calls; will be added when that feature lands.
|
|
197
233
|
- Outbound `culture.s2s.messages` (records inbound only — outbound needs a clean verb-extraction site).
|
|
198
234
|
- OTEL Logs export of audit records (best-effort duplicate; JSONL stays source of truth either way).
|
|
199
235
|
- `audit-prune` CLI for retention; operators prune manually in v1.
|