agentirc-cli 8.7.1__tar.gz → 9.0.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.
- agentirc_cli-9.0.0/.claude/skills/pr-review/SKILL.md +126 -0
- agentirc_cli-9.0.0/.claude/skills/pr-review/scripts/portability-lint.sh +56 -0
- agentirc_cli-9.0.0/.claude/skills/pr-review/scripts/pr-batch.sh +57 -0
- agentirc_cli-9.0.0/.claude/skills/pr-review/scripts/pr-comments.sh +100 -0
- agentirc_cli-9.0.0/.claude/skills/pr-review/scripts/pr-reply.sh +66 -0
- agentirc_cli-9.0.0/.claude/skills/pr-review/scripts/pr-status.sh +161 -0
- agentirc_cli-9.0.0/.claude/skills/pr-review/scripts/workflow.sh +99 -0
- agentirc_cli-9.0.0/.claude/skills.local.yaml.example +12 -0
- agentirc_cli-9.0.0/.github/workflows/publish.yml +130 -0
- agentirc_cli-9.0.0/.github/workflows/tests.yml +128 -0
- {agentirc_cli-8.7.1 → agentirc_cli-9.0.0}/.gitignore +44 -41
- agentirc_cli-9.0.0/CLAUDE.md +126 -0
- {agentirc_cli-8.7.1 → agentirc_cli-9.0.0}/LICENSE +1 -1
- agentirc_cli-9.0.0/PKG-INFO +52 -0
- agentirc_cli-9.0.0/README.md +2 -0
- agentirc_cli-9.0.0/agentirc/__init__.py +9 -0
- agentirc_cli-9.0.0/agentirc/__main__.py +4 -0
- agentirc_cli-9.0.0/agentirc/cli.py +104 -0
- agentirc_cli-9.0.0/docs/steward/onboarding.md +108 -0
- agentirc_cli-9.0.0/docs/superpowers/specs/2026-04-30-bootstrap-design.md +248 -0
- agentirc_cli-9.0.0/pyproject.toml +51 -0
- agentirc_cli-9.0.0/tests/test_cli.py +95 -0
- agentirc_cli-9.0.0/uv.lock +564 -0
- agentirc_cli-8.7.1/.claude/agents/doc-test-alignment.md +0 -154
- agentirc_cli-8.7.1/.claude/skills/pr-review/SKILL.md +0 -218
- agentirc_cli-8.7.1/.claude/skills/run-tests/SKILL.md +0 -48
- agentirc_cli-8.7.1/.claude/skills/run-tests/scripts/test.sh +0 -47
- agentirc_cli-8.7.1/.flake8 +0 -37
- agentirc_cli-8.7.1/.github/workflows/docs-check.yml +0 -22
- agentirc_cli-8.7.1/.github/workflows/publish.yml +0 -111
- agentirc_cli-8.7.1/.github/workflows/security-checks.yml +0 -79
- agentirc_cli-8.7.1/.github/workflows/tests.yml +0 -78
- agentirc_cli-8.7.1/.markdownlint-cli2.yaml +0 -30
- agentirc_cli-8.7.1/.pr_agent.toml +0 -38
- agentirc_cli-8.7.1/.pre-commit-config.yaml +0 -48
- agentirc_cli-8.7.1/.pylintrc +0 -87
- agentirc_cli-8.7.1/CHANGELOG.md +0 -1298
- agentirc_cli-8.7.1/CLAUDE.md +0 -88
- agentirc_cli-8.7.1/Gemfile +0 -8
- agentirc_cli-8.7.1/Gemfile.lock +0 -258
- agentirc_cli-8.7.1/PKG-INFO +0 -65
- agentirc_cli-8.7.1/README.md +0 -34
- agentirc_cli-8.7.1/SECURITY.md +0 -39
- agentirc_cli-8.7.1/_config.base.yml +0 -54
- agentirc_cli-8.7.1/_config.culture.yml +0 -56
- agentirc_cli-8.7.1/_data/sites.yml +0 -5
- agentirc_cli-8.7.1/_includes/head_custom.html +0 -8
- agentirc_cli-8.7.1/_sass/color_schemes/anthropic.scss +0 -34
- agentirc_cli-8.7.1/_sass/color_schemes/dark-terminal.scss +0 -40
- agentirc_cli-8.7.1/_sass/custom/custom.scss +0 -348
- agentirc_cli-8.7.1/assets/images/IMG_3183.png +0 -0
- agentirc_cli-8.7.1/assets/images/apple-touch-icon.png +0 -0
- agentirc_cli-8.7.1/assets/images/favicon-16x16.png +0 -0
- agentirc_cli-8.7.1/assets/images/favicon-32x32.png +0 -0
- agentirc_cli-8.7.1/assets/images/favicon.ico +0 -0
- agentirc_cli-8.7.1/assets/images/og-agentirc.png +0 -0
- agentirc_cli-8.7.1/assets/images/og-culture.png +0 -0
- agentirc_cli-8.7.1/culture/__init__.py +0 -13
- agentirc_cli-8.7.1/culture/__main__.py +0 -6
- agentirc_cli-8.7.1/culture/agentirc/CLAUDE.md +0 -125
- agentirc_cli-8.7.1/culture/agentirc/__main__.py +0 -67
- agentirc_cli-8.7.1/culture/agentirc/channel.py +0 -80
- agentirc_cli-8.7.1/culture/agentirc/client.py +0 -1056
- agentirc_cli-8.7.1/culture/agentirc/config.py +0 -49
- agentirc_cli-8.7.1/culture/agentirc/docs/agentirc-architecture.md +0 -178
- agentirc_cli-8.7.1/culture/agentirc/docs/agentirc-features.md +0 -192
- agentirc_cli-8.7.1/culture/agentirc/docs/agentirc-skill.md +0 -293
- agentirc_cli-8.7.1/culture/agentirc/docs/agentirc.md +0 -74
- agentirc_cli-8.7.1/culture/agentirc/events.py +0 -117
- agentirc_cli-8.7.1/culture/agentirc/history_store.py +0 -91
- agentirc_cli-8.7.1/culture/agentirc/ircd.py +0 -719
- agentirc_cli-8.7.1/culture/agentirc/remote_client.py +0 -43
- agentirc_cli-8.7.1/culture/agentirc/room_store.py +0 -64
- agentirc_cli-8.7.1/culture/agentirc/rooms_util.py +0 -56
- agentirc_cli-8.7.1/culture/agentirc/server_link.py +0 -1166
- agentirc_cli-8.7.1/culture/agentirc/skill.py +0 -61
- agentirc_cli-8.7.1/culture/agentirc/skills/__init__.py +0 -0
- agentirc_cli-8.7.1/culture/agentirc/skills/history.py +0 -225
- agentirc_cli-8.7.1/culture/agentirc/skills/icon.py +0 -52
- agentirc_cli-8.7.1/culture/agentirc/skills/rooms.py +0 -834
- agentirc_cli-8.7.1/culture/agentirc/skills/threads.py +0 -710
- agentirc_cli-8.7.1/culture/agentirc/thread_store.py +0 -52
- agentirc_cli-8.7.1/culture/aio.py +0 -12
- agentirc_cli-8.7.1/culture/bots/__init__.py +0 -0
- agentirc_cli-8.7.1/culture/bots/bot.py +0 -264
- agentirc_cli-8.7.1/culture/bots/bot_manager.py +0 -226
- agentirc_cli-8.7.1/culture/bots/config.py +0 -162
- agentirc_cli-8.7.1/culture/bots/filter_dsl.py +0 -339
- agentirc_cli-8.7.1/culture/bots/http_listener.py +0 -118
- agentirc_cli-8.7.1/culture/bots/system/__init__.py +0 -36
- agentirc_cli-8.7.1/culture/bots/system/welcome/__init__.py +0 -1
- agentirc_cli-8.7.1/culture/bots/system/welcome/bot.yaml +0 -11
- agentirc_cli-8.7.1/culture/bots/system/welcome/handler.py +0 -1
- agentirc_cli-8.7.1/culture/bots/template_engine.py +0 -68
- agentirc_cli-8.7.1/culture/bots/virtual_client.py +0 -231
- agentirc_cli-8.7.1/culture/cli/__init__.py +0 -74
- agentirc_cli-8.7.1/culture/cli/_passthrough.py +0 -116
- agentirc_cli-8.7.1/culture/cli/afi.py +0 -71
- agentirc_cli-8.7.1/culture/cli/agent.py +0 -1089
- agentirc_cli-8.7.1/culture/cli/bot.py +0 -299
- agentirc_cli-8.7.1/culture/cli/channel.py +0 -421
- agentirc_cli-8.7.1/culture/cli/devex.py +0 -71
- agentirc_cli-8.7.1/culture/cli/introspect.py +0 -189
- agentirc_cli-8.7.1/culture/cli/mesh.py +0 -734
- agentirc_cli-8.7.1/culture/cli/server.py +0 -654
- agentirc_cli-8.7.1/culture/cli/shared/__init__.py +0 -0
- agentirc_cli-8.7.1/culture/cli/shared/constants.py +0 -54
- agentirc_cli-8.7.1/culture/cli/shared/display.py +0 -164
- agentirc_cli-8.7.1/culture/cli/shared/formatting.py +0 -5
- agentirc_cli-8.7.1/culture/cli/shared/ipc.py +0 -70
- agentirc_cli-8.7.1/culture/cli/shared/mesh.py +0 -102
- agentirc_cli-8.7.1/culture/cli/shared/process.py +0 -144
- agentirc_cli-8.7.1/culture/cli/skills.py +0 -151
- agentirc_cli-8.7.1/culture/clients/__init__.py +0 -0
- agentirc_cli-8.7.1/culture/clients/acp/__init__.py +0 -0
- agentirc_cli-8.7.1/culture/clients/acp/agent_runner.py +0 -496
- agentirc_cli-8.7.1/culture/clients/acp/config.py +0 -330
- agentirc_cli-8.7.1/culture/clients/acp/culture.yaml +0 -32
- agentirc_cli-8.7.1/culture/clients/acp/daemon.py +0 -956
- agentirc_cli-8.7.1/culture/clients/acp/ipc.py +0 -41
- agentirc_cli-8.7.1/culture/clients/acp/irc_transport.py +0 -384
- agentirc_cli-8.7.1/culture/clients/acp/message_buffer.py +0 -71
- agentirc_cli-8.7.1/culture/clients/acp/skill/SKILL.md +0 -194
- agentirc_cli-8.7.1/culture/clients/acp/skill/__init__.py +0 -0
- agentirc_cli-8.7.1/culture/clients/acp/skill/irc_client.py +0 -325
- agentirc_cli-8.7.1/culture/clients/acp/socket_server.py +0 -122
- agentirc_cli-8.7.1/culture/clients/acp/supervisor.py +0 -150
- agentirc_cli-8.7.1/culture/clients/acp/telemetry.py +0 -318
- agentirc_cli-8.7.1/culture/clients/acp/webhook.py +0 -64
- agentirc_cli-8.7.1/culture/clients/claude/__init__.py +0 -0
- agentirc_cli-8.7.1/culture/clients/claude/__main__.py +0 -93
- agentirc_cli-8.7.1/culture/clients/claude/agent_runner.py +0 -231
- agentirc_cli-8.7.1/culture/clients/claude/config.py +0 -440
- agentirc_cli-8.7.1/culture/clients/claude/culture.yaml +0 -29
- agentirc_cli-8.7.1/culture/clients/claude/daemon.py +0 -848
- agentirc_cli-8.7.1/culture/clients/claude/ipc.py +0 -41
- agentirc_cli-8.7.1/culture/clients/claude/irc_transport.py +0 -384
- agentirc_cli-8.7.1/culture/clients/claude/message_buffer.py +0 -71
- agentirc_cli-8.7.1/culture/clients/claude/skill/SKILL.md +0 -187
- agentirc_cli-8.7.1/culture/clients/claude/skill/__init__.py +0 -0
- agentirc_cli-8.7.1/culture/clients/claude/skill/irc_client.py +0 -322
- agentirc_cli-8.7.1/culture/clients/claude/socket_server.py +0 -126
- agentirc_cli-8.7.1/culture/clients/claude/supervisor.py +0 -150
- agentirc_cli-8.7.1/culture/clients/claude/telemetry.py +0 -318
- agentirc_cli-8.7.1/culture/clients/claude/webhook.py +0 -64
- agentirc_cli-8.7.1/culture/clients/codex/__init__.py +0 -0
- agentirc_cli-8.7.1/culture/clients/codex/agent_runner.py +0 -408
- agentirc_cli-8.7.1/culture/clients/codex/config.py +0 -330
- agentirc_cli-8.7.1/culture/clients/codex/culture.yaml +0 -29
- agentirc_cli-8.7.1/culture/clients/codex/daemon.py +0 -945
- agentirc_cli-8.7.1/culture/clients/codex/ipc.py +0 -41
- agentirc_cli-8.7.1/culture/clients/codex/irc_transport.py +0 -384
- agentirc_cli-8.7.1/culture/clients/codex/message_buffer.py +0 -71
- agentirc_cli-8.7.1/culture/clients/codex/skill/SKILL.md +0 -194
- agentirc_cli-8.7.1/culture/clients/codex/skill/__init__.py +0 -0
- agentirc_cli-8.7.1/culture/clients/codex/skill/irc_client.py +0 -322
- agentirc_cli-8.7.1/culture/clients/codex/socket_server.py +0 -126
- agentirc_cli-8.7.1/culture/clients/codex/supervisor.py +0 -174
- agentirc_cli-8.7.1/culture/clients/codex/telemetry.py +0 -318
- agentirc_cli-8.7.1/culture/clients/codex/webhook.py +0 -64
- agentirc_cli-8.7.1/culture/clients/copilot/__init__.py +0 -0
- agentirc_cli-8.7.1/culture/clients/copilot/agent_runner.py +0 -247
- agentirc_cli-8.7.1/culture/clients/copilot/config.py +0 -328
- agentirc_cli-8.7.1/culture/clients/copilot/culture.yaml +0 -29
- agentirc_cli-8.7.1/culture/clients/copilot/daemon.py +0 -923
- agentirc_cli-8.7.1/culture/clients/copilot/ipc.py +0 -41
- agentirc_cli-8.7.1/culture/clients/copilot/irc_transport.py +0 -384
- agentirc_cli-8.7.1/culture/clients/copilot/message_buffer.py +0 -71
- agentirc_cli-8.7.1/culture/clients/copilot/skill/SKILL.md +0 -194
- agentirc_cli-8.7.1/culture/clients/copilot/skill/__init__.py +0 -0
- agentirc_cli-8.7.1/culture/clients/copilot/skill/irc_client.py +0 -325
- agentirc_cli-8.7.1/culture/clients/copilot/socket_server.py +0 -126
- agentirc_cli-8.7.1/culture/clients/copilot/supervisor.py +0 -170
- agentirc_cli-8.7.1/culture/clients/copilot/telemetry.py +0 -318
- agentirc_cli-8.7.1/culture/clients/copilot/webhook.py +0 -65
- agentirc_cli-8.7.1/culture/config.py +0 -744
- agentirc_cli-8.7.1/culture/console/__init__.py +0 -1
- agentirc_cli-8.7.1/culture/console/app.py +0 -724
- agentirc_cli-8.7.1/culture/console/client.py +0 -427
- agentirc_cli-8.7.1/culture/console/commands.py +0 -95
- agentirc_cli-8.7.1/culture/console/status.py +0 -74
- agentirc_cli-8.7.1/culture/console/widgets/__init__.py +0 -1
- agentirc_cli-8.7.1/culture/console/widgets/chat.py +0 -227
- agentirc_cli-8.7.1/culture/console/widgets/info_panel.py +0 -172
- agentirc_cli-8.7.1/culture/console/widgets/sidebar.py +0 -205
- agentirc_cli-8.7.1/culture/constants.py +0 -17
- agentirc_cli-8.7.1/culture/credentials.py +0 -167
- agentirc_cli-8.7.1/culture/formatting.py +0 -19
- agentirc_cli-8.7.1/culture/learn_prompt.py +0 -299
- agentirc_cli-8.7.1/culture/mesh_config.py +0 -139
- agentirc_cli-8.7.1/culture/observer.py +0 -267
- agentirc_cli-8.7.1/culture/overview/__init__.py +0 -1
- agentirc_cli-8.7.1/culture/overview/collector.py +0 -469
- agentirc_cli-8.7.1/culture/overview/model.py +0 -80
- agentirc_cli-8.7.1/culture/overview/renderer_text.py +0 -267
- agentirc_cli-8.7.1/culture/overview/renderer_web.py +0 -272
- agentirc_cli-8.7.1/culture/overview/web/style.css +0 -88
- agentirc_cli-8.7.1/culture/persistence.py +0 -309
- agentirc_cli-8.7.1/culture/pidfile.py +0 -164
- agentirc_cli-8.7.1/culture/protocol/__init__.py +0 -0
- agentirc_cli-8.7.1/culture/protocol/commands.py +0 -43
- agentirc_cli-8.7.1/culture/protocol/extensions/audit.md +0 -109
- agentirc_cli-8.7.1/culture/protocol/extensions/events.md +0 -145
- agentirc_cli-8.7.1/culture/protocol/extensions/federation.md +0 -120
- agentirc_cli-8.7.1/culture/protocol/extensions/history.md +0 -117
- agentirc_cli-8.7.1/culture/protocol/extensions/icons.md +0 -117
- agentirc_cli-8.7.1/culture/protocol/extensions/rooms.md +0 -69
- agentirc_cli-8.7.1/culture/protocol/extensions/tags.md +0 -32
- agentirc_cli-8.7.1/culture/protocol/extensions/threads.md +0 -296
- agentirc_cli-8.7.1/culture/protocol/extensions/tracing.md +0 -37
- agentirc_cli-8.7.1/culture/protocol/message.py +0 -128
- agentirc_cli-8.7.1/culture/protocol/protocol-index.md +0 -9
- agentirc_cli-8.7.1/culture/protocol/replies.py +0 -52
- agentirc_cli-8.7.1/culture/skills/culture/SKILL.md +0 -370
- agentirc_cli-8.7.1/culture/telemetry/__init__.py +0 -34
- agentirc_cli-8.7.1/culture/telemetry/audit.py +0 -380
- agentirc_cli-8.7.1/culture/telemetry/context.py +0 -121
- agentirc_cli-8.7.1/culture/telemetry/metrics.py +0 -250
- agentirc_cli-8.7.1/culture/telemetry/tracing.py +0 -117
- agentirc_cli-8.7.1/docs/README.md +0 -10
- agentirc_cli-8.7.1/docs/agentirc/architecture-overview.md +0 -82
- agentirc_cli-8.7.1/docs/agentirc/audit.md +0 -154
- agentirc_cli-8.7.1/docs/agentirc/bots.md +0 -242
- agentirc_cli-8.7.1/docs/agentirc/events.md +0 -164
- agentirc_cli-8.7.1/docs/agentirc/harness-telemetry.md +0 -302
- agentirc_cli-8.7.1/docs/agentirc/index.md +0 -94
- agentirc_cli-8.7.1/docs/agentirc/otelcol-template.yaml +0 -25
- agentirc_cli-8.7.1/docs/agentirc/telemetry.md +0 -238
- agentirc_cli-8.7.1/docs/agentirc/why-agentirc.md +0 -32
- agentirc_cli-8.7.1/docs/culture/agent-lifecycle.md +0 -265
- agentirc_cli-8.7.1/docs/culture/choose-a-harness.md +0 -44
- agentirc_cli-8.7.1/docs/culture/features.md +0 -90
- agentirc_cli-8.7.1/docs/culture/index.md +0 -87
- agentirc_cli-8.7.1/docs/culture/mental-model.md +0 -74
- agentirc_cli-8.7.1/docs/culture/operate.md +0 -16
- agentirc_cli-8.7.1/docs/culture/patterns.md +0 -67
- agentirc_cli-8.7.1/docs/culture/quickstart.md +0 -137
- agentirc_cli-8.7.1/docs/culture/reflective-development.md +0 -134
- agentirc_cli-8.7.1/docs/culture/vision-patterns-index.md +0 -12
- agentirc_cli-8.7.1/docs/culture/vision.md +0 -85
- agentirc_cli-8.7.1/docs/culture/what-is-culture.md +0 -93
- agentirc_cli-8.7.1/docs/reference/architecture/agent-harness-spec.md +0 -498
- agentirc_cli-8.7.1/docs/reference/architecture/index.md +0 -27
- agentirc_cli-8.7.1/docs/reference/architecture/layers.md +0 -350
- agentirc_cli-8.7.1/docs/reference/architecture/subsites.md +0 -111
- agentirc_cli-8.7.1/docs/reference/architecture/threads.md +0 -210
- agentirc_cli-8.7.1/docs/reference/cli/afi.md +0 -95
- agentirc_cli-8.7.1/docs/reference/cli/commands.md +0 -193
- agentirc_cli-8.7.1/docs/reference/cli/devex.md +0 -129
- agentirc_cli-8.7.1/docs/reference/cli/index.md +0 -429
- agentirc_cli-8.7.1/docs/reference/console.md +0 -90
- agentirc_cli-8.7.1/docs/reference/harnesses/acp.md +0 -329
- agentirc_cli-8.7.1/docs/reference/harnesses/claude.md +0 -446
- agentirc_cli-8.7.1/docs/reference/harnesses/codex.md +0 -364
- agentirc_cli-8.7.1/docs/reference/harnesses/copilot.md +0 -352
- agentirc_cli-8.7.1/docs/reference/harnesses/index.md +0 -34
- agentirc_cli-8.7.1/docs/reference/index.md +0 -12
- agentirc_cli-8.7.1/docs/reference/server/architecture.md +0 -185
- agentirc_cli-8.7.1/docs/reference/server/config.md +0 -280
- agentirc_cli-8.7.1/docs/reference/server/deployment.md +0 -113
- agentirc_cli-8.7.1/docs/reference/server/index.md +0 -78
- agentirc_cli-8.7.1/docs/reference/server/security.md +0 -118
- agentirc_cli-8.7.1/docs/resources/github-copilot-sdk-instructions.md +0 -766
- agentirc_cli-8.7.1/docs/resources/positioning.md +0 -44
- agentirc_cli-8.7.1/docs/shared/concepts/federation.md +0 -71
- agentirc_cli-8.7.1/docs/shared/concepts/harnesses.md +0 -77
- agentirc_cli-8.7.1/docs/shared/concepts/humans-and-agents.md +0 -54
- agentirc_cli-8.7.1/docs/shared/concepts/index.md +0 -12
- agentirc_cli-8.7.1/docs/shared/concepts/persistence.md +0 -70
- agentirc_cli-8.7.1/docs/shared/concepts/rooms.md +0 -91
- agentirc_cli-8.7.1/docs/shared/demos/magic-demo.md +0 -87
- agentirc_cli-8.7.1/docs/shared/guides/first-session.md +0 -64
- agentirc_cli-8.7.1/docs/shared/guides/index.md +0 -12
- agentirc_cli-8.7.1/docs/shared/guides/join-as-human.md +0 -95
- agentirc_cli-8.7.1/docs/shared/guides/local-setup.md +0 -71
- agentirc_cli-8.7.1/docs/shared/guides/multi-machine.md +0 -85
- agentirc_cli-8.7.1/docs/shared/use-cases/01-pair-programming.md +0 -226
- agentirc_cli-8.7.1/docs/shared/use-cases/02-code-review-ensemble.md +0 -221
- agentirc_cli-8.7.1/docs/shared/use-cases/03-cross-server-delegation.md +0 -193
- agentirc_cli-8.7.1/docs/shared/use-cases/04-knowledge-propagation.md +0 -127
- agentirc_cli-8.7.1/docs/shared/use-cases/05-the-observer.md +0 -196
- agentirc_cli-8.7.1/docs/shared/use-cases/06-cross-server-ops.md +0 -173
- agentirc_cli-8.7.1/docs/shared/use-cases/07-supervisor-intervention.md +0 -266
- agentirc_cli-8.7.1/docs/shared/use-cases/08-apps-as-agents.md +0 -139
- agentirc_cli-8.7.1/docs/shared/use-cases/09-research-swarm.md +0 -233
- agentirc_cli-8.7.1/docs/shared/use-cases/10-agent-lifecycle.md +0 -416
- agentirc_cli-8.7.1/docs/shared/use-cases-index.md +0 -27
- agentirc_cli-8.7.1/docs/superpowers/plans/2026-03-19-layer1-core-irc.md +0 -1654
- agentirc_cli-8.7.1/docs/superpowers/plans/2026-03-21-layer5-agent-harness.md +0 -3120
- agentirc_cli-8.7.1/docs/superpowers/plans/2026-03-30-overview.md +0 -1635
- agentirc_cli-8.7.1/docs/superpowers/plans/2026-03-30-rooms-management.md +0 -3213
- agentirc_cli-8.7.1/docs/superpowers/plans/2026-04-02-conversation-threads.md +0 -1885
- agentirc_cli-8.7.1/docs/superpowers/plans/2026-04-02-ops-tooling.md +0 -1763
- agentirc_cli-8.7.1/docs/superpowers/plans/2026-04-04-culture-rename.md +0 -801
- agentirc_cli-8.7.1/docs/superpowers/plans/2026-04-05-docs-speak-culture.md +0 -1205
- agentirc_cli-8.7.1/docs/superpowers/plans/2026-04-06-console-chat.md +0 -2246
- agentirc_cli-8.7.1/docs/superpowers/plans/2026-04-09-decentralized-agent-config.md +0 -2131
- agentirc_cli-8.7.1/docs/superpowers/plans/2026-04-12-console-enhancements.md +0 -732
- agentirc_cli-8.7.1/docs/superpowers/plans/2026-04-15-mesh-events.md +0 -3252
- agentirc_cli-8.7.1/docs/superpowers/plans/2026-04-18-culture-dev-positioning.md +0 -812
- agentirc_cli-8.7.1/docs/superpowers/plans/2026-04-22-agex-integration.md +0 -999
- agentirc_cli-8.7.1/docs/superpowers/plans/2026-04-24-otel-foundation.md +0 -2159
- agentirc_cli-8.7.1/docs/superpowers/plans/2026-04-25-otel-federation.md +0 -229
- agentirc_cli-8.7.1/docs/superpowers/plans/2026-04-26-otel-metrics.md +0 -303
- agentirc_cli-8.7.1/docs/superpowers/plans/2026-04-27-otel-audit.md +0 -247
- agentirc_cli-8.7.1/docs/superpowers/plans/2026-04-28-otel-harness.md +0 -272
- agentirc_cli-8.7.1/docs/superpowers/specs/2026-03-19-agentirc-design.md +0 -411
- agentirc_cli-8.7.1/docs/superpowers/specs/2026-03-21-layer5-agent-harness-design.md +0 -484
- agentirc_cli-8.7.1/docs/superpowers/specs/2026-03-30-overview-design.md +0 -328
- agentirc_cli-8.7.1/docs/superpowers/specs/2026-03-30-rooms-management-design.md +0 -488
- agentirc_cli-8.7.1/docs/superpowers/specs/2026-04-02-conversation-threads-design.md +0 -326
- agentirc_cli-8.7.1/docs/superpowers/specs/2026-04-02-ops-tooling-design.md +0 -373
- agentirc_cli-8.7.1/docs/superpowers/specs/2026-04-03-bots-webhooks-design.md +0 -353
- agentirc_cli-8.7.1/docs/superpowers/specs/2026-04-04-culture-rename-design.md +0 -177
- agentirc_cli-8.7.1/docs/superpowers/specs/2026-04-05-docs-speak-culture-design.md +0 -277
- agentirc_cli-8.7.1/docs/superpowers/specs/2026-04-05-lifecycle-reframe-design.md +0 -219
- agentirc_cli-8.7.1/docs/superpowers/specs/2026-04-06-cli-reorganization-design.md +0 -212
- agentirc_cli-8.7.1/docs/superpowers/specs/2026-04-06-console-chat-design.md +0 -298
- agentirc_cli-8.7.1/docs/superpowers/specs/2026-04-07-entity-archiving-design.md +0 -305
- agentirc_cli-8.7.1/docs/superpowers/specs/2026-04-07-reflective-development-reframe-design.md +0 -165
- agentirc_cli-8.7.1/docs/superpowers/specs/2026-04-08-reflective-development-deepening-design.md +0 -179
- agentirc_cli-8.7.1/docs/superpowers/specs/2026-04-09-decentralized-agent-config-design.md +0 -361
- agentirc_cli-8.7.1/docs/superpowers/specs/2026-04-12-console-enhancements-design.md +0 -203
- agentirc_cli-8.7.1/docs/superpowers/specs/2026-04-15-mesh-events-design.md +0 -380
- agentirc_cli-8.7.1/docs/superpowers/specs/2026-04-17-sites-repositioning-design.md +0 -101
- agentirc_cli-8.7.1/docs/superpowers/specs/2026-04-18-culture-dev-positioning-design.md +0 -280
- agentirc_cli-8.7.1/docs/superpowers/specs/2026-04-22-agex-integration-design.md +0 -258
- agentirc_cli-8.7.1/docs/superpowers/specs/2026-04-24-otel-observability-design.md +0 -334
- agentirc_cli-8.7.1/favicon.ico +0 -0
- agentirc_cli-8.7.1/packages/agent-harness/README.md +0 -56
- agentirc_cli-8.7.1/packages/agent-harness/config.py +0 -299
- agentirc_cli-8.7.1/packages/agent-harness/culture.yaml +0 -28
- agentirc_cli-8.7.1/packages/agent-harness/daemon.py +0 -637
- agentirc_cli-8.7.1/packages/agent-harness/ipc.py +0 -38
- agentirc_cli-8.7.1/packages/agent-harness/irc_transport.py +0 -387
- agentirc_cli-8.7.1/packages/agent-harness/message_buffer.py +0 -71
- agentirc_cli-8.7.1/packages/agent-harness/skill/SKILL.md +0 -57
- agentirc_cli-8.7.1/packages/agent-harness/skill/irc_client.py +0 -325
- agentirc_cli-8.7.1/packages/agent-harness/socket_server.py +0 -129
- agentirc_cli-8.7.1/packages/agent-harness/telemetry.py +0 -315
- agentirc_cli-8.7.1/packages/agent-harness/webhook.py +0 -67
- agentirc_cli-8.7.1/plugins/claude-code/.claude-plugin/plugin.json +0 -6
- agentirc_cli-8.7.1/plugins/claude-code/skills/culture/SKILL.md +0 -363
- agentirc_cli-8.7.1/plugins/claude-code/skills/irc/SKILL.md +0 -187
- agentirc_cli-8.7.1/plugins/codex/skills/culture-irc/SKILL.md +0 -194
- agentirc_cli-8.7.1/pyproject.toml +0 -101
- agentirc_cli-8.7.1/robots.txt +0 -9
- agentirc_cli-8.7.1/sitemap-agentirc.html +0 -17
- agentirc_cli-8.7.1/sitemap-main.html +0 -19
- agentirc_cli-8.7.1/sitemap.html +0 -13
- agentirc_cli-8.7.1/sonar-project.properties +0 -32
- agentirc_cli-8.7.1/tests/__init__.py +0 -0
- agentirc_cli-8.7.1/tests/conftest.py +0 -389
- agentirc_cli-8.7.1/tests/harness/__init__.py +0 -0
- agentirc_cli-8.7.1/tests/harness/conftest.py +0 -89
- agentirc_cli-8.7.1/tests/harness/test_agent_runner_acp.py +0 -233
- agentirc_cli-8.7.1/tests/harness/test_agent_runner_claude.py +0 -449
- agentirc_cli-8.7.1/tests/harness/test_agent_runner_codex.py +0 -229
- agentirc_cli-8.7.1/tests/harness/test_agent_runner_copilot.py +0 -256
- agentirc_cli-8.7.1/tests/harness/test_all_backends_parity.py +0 -398
- agentirc_cli-8.7.1/tests/harness/test_daemon_telemetry.py +0 -72
- agentirc_cli-8.7.1/tests/harness/test_irc_transport_propagation.py +0 -447
- agentirc_cli-8.7.1/tests/harness/test_record_llm_call.py +0 -245
- agentirc_cli-8.7.1/tests/harness/test_telemetry_module.py +0 -264
- agentirc_cli-8.7.1/tests/telemetry/__init__.py +0 -0
- agentirc_cli-8.7.1/tests/telemetry/_fakes.py +0 -26
- agentirc_cli-8.7.1/tests/telemetry/_metrics_helpers.py +0 -75
- agentirc_cli-8.7.1/tests/telemetry/conftest.py +0 -33
- agentirc_cli-8.7.1/tests/telemetry/test_audit_emit.py +0 -145
- agentirc_cli-8.7.1/tests/telemetry/test_audit_federation.py +0 -132
- agentirc_cli-8.7.1/tests/telemetry/test_audit_lifecycle.py +0 -69
- agentirc_cli-8.7.1/tests/telemetry/test_audit_module.py +0 -306
- agentirc_cli-8.7.1/tests/telemetry/test_audit_parse_error.py +0 -177
- agentirc_cli-8.7.1/tests/telemetry/test_bot_event_dispatch_span.py +0 -138
- agentirc_cli-8.7.1/tests/telemetry/test_bot_run_span.py +0 -91
- agentirc_cli-8.7.1/tests/telemetry/test_config.py +0 -26
- agentirc_cli-8.7.1/tests/telemetry/test_config_load.py +0 -36
- agentirc_cli-8.7.1/tests/telemetry/test_context.py +0 -147
- agentirc_cli-8.7.1/tests/telemetry/test_dispatch_span.py +0 -45
- agentirc_cli-8.7.1/tests/telemetry/test_emit_event_span.py +0 -42
- agentirc_cli-8.7.1/tests/telemetry/test_federation_propagation.py +0 -141
- agentirc_cli-8.7.1/tests/telemetry/test_metrics_bots.py +0 -127
- agentirc_cli-8.7.1/tests/telemetry/test_metrics_clients.py +0 -79
- agentirc_cli-8.7.1/tests/telemetry/test_metrics_events.py +0 -81
- agentirc_cli-8.7.1/tests/telemetry/test_metrics_init.py +0 -58
- agentirc_cli-8.7.1/tests/telemetry/test_metrics_irc.py +0 -99
- agentirc_cli-8.7.1/tests/telemetry/test_metrics_s2s.py +0 -160
- agentirc_cli-8.7.1/tests/telemetry/test_metrics_trace_inbound.py +0 -127
- agentirc_cli-8.7.1/tests/telemetry/test_metrics_webhook.py +0 -148
- agentirc_cli-8.7.1/tests/telemetry/test_outbound_inject.py +0 -70
- agentirc_cli-8.7.1/tests/telemetry/test_parse_error.py +0 -33
- agentirc_cli-8.7.1/tests/telemetry/test_privmsg_span.py +0 -45
- agentirc_cli-8.7.1/tests/telemetry/test_s2s_dispatch_span.py +0 -156
- agentirc_cli-8.7.1/tests/telemetry/test_s2s_relay_span.py +0 -114
- agentirc_cli-8.7.1/tests/telemetry/test_s2s_session_span.py +0 -64
- agentirc_cli-8.7.1/tests/telemetry/test_server_init.py +0 -29
- agentirc_cli-8.7.1/tests/telemetry/test_server_link_inject.py +0 -124
- agentirc_cli-8.7.1/tests/telemetry/test_session_span.py +0 -105
- agentirc_cli-8.7.1/tests/telemetry/test_tracing.py +0 -49
- agentirc_cli-8.7.1/tests/telemetry/test_webhook_http_span.py +0 -45
- agentirc_cli-8.7.1/tests/test_acp_daemon.py +0 -256
- agentirc_cli-8.7.1/tests/test_agent_runner.py +0 -209
- agentirc_cli-8.7.1/tests/test_archive.py +0 -1008
- agentirc_cli-8.7.1/tests/test_bot.py +0 -174
- agentirc_cli-8.7.1/tests/test_bot_config.py +0 -98
- agentirc_cli-8.7.1/tests/test_bot_config_fires_event_toplevel.py +0 -114
- agentirc_cli-8.7.1/tests/test_bot_manager.py +0 -147
- agentirc_cli-8.7.1/tests/test_bots_integration.py +0 -161
- agentirc_cli-8.7.1/tests/test_channel.py +0 -131
- agentirc_cli-8.7.1/tests/test_channel_cli.py +0 -301
- agentirc_cli-8.7.1/tests/test_cli_afi.py +0 -111
- agentirc_cli-8.7.1/tests/test_cli_devex.py +0 -53
- agentirc_cli-8.7.1/tests/test_cli_introspect.py +0 -155
- agentirc_cli-8.7.1/tests/test_cli_passthrough.py +0 -146
- agentirc_cli-8.7.1/tests/test_codex_daemon.py +0 -284
- agentirc_cli-8.7.1/tests/test_connection.py +0 -135
- agentirc_cli-8.7.1/tests/test_console_chat_markdown.py +0 -241
- agentirc_cli-8.7.1/tests/test_console_client.py +0 -398
- agentirc_cli-8.7.1/tests/test_console_commands.py +0 -133
- agentirc_cli-8.7.1/tests/test_console_connection.py +0 -66
- agentirc_cli-8.7.1/tests/test_console_fixes_224_227.py +0 -202
- agentirc_cli-8.7.1/tests/test_console_icons.py +0 -227
- agentirc_cli-8.7.1/tests/test_console_integration.py +0 -65
- agentirc_cli-8.7.1/tests/test_console_status.py +0 -53
- agentirc_cli-8.7.1/tests/test_constants.py +0 -86
- agentirc_cli-8.7.1/tests/test_copilot_daemon.py +0 -253
- agentirc_cli-8.7.1/tests/test_credentials.py +0 -24
- agentirc_cli-8.7.1/tests/test_culture_config.py +0 -499
- agentirc_cli-8.7.1/tests/test_daemon.py +0 -95
- agentirc_cli-8.7.1/tests/test_daemon_config.py +0 -714
- agentirc_cli-8.7.1/tests/test_daemon_ipc.py +0 -160
- agentirc_cli-8.7.1/tests/test_discovery.py +0 -169
- agentirc_cli-8.7.1/tests/test_display.py +0 -226
- agentirc_cli-8.7.1/tests/test_events_basic.py +0 -292
- agentirc_cli-8.7.1/tests/test_events_bot_chain.py +0 -59
- agentirc_cli-8.7.1/tests/test_events_bot_trigger.py +0 -99
- agentirc_cli-8.7.1/tests/test_events_cap_fallback.py +0 -59
- agentirc_cli-8.7.1/tests/test_events_catalog.py +0 -70
- agentirc_cli-8.7.1/tests/test_events_federation.py +0 -110
- agentirc_cli-8.7.1/tests/test_events_history.py +0 -64
- agentirc_cli-8.7.1/tests/test_events_lifecycle.py +0 -343
- agentirc_cli-8.7.1/tests/test_events_reserved_nick.py +0 -68
- agentirc_cli-8.7.1/tests/test_federation.py +0 -1251
- agentirc_cli-8.7.1/tests/test_filter_dsl.py +0 -99
- agentirc_cli-8.7.1/tests/test_history.py +0 -553
- agentirc_cli-8.7.1/tests/test_http_listener.py +0 -147
- agentirc_cli-8.7.1/tests/test_integration_layer5.py +0 -109
- agentirc_cli-8.7.1/tests/test_ipc.py +0 -55
- agentirc_cli-8.7.1/tests/test_irc_transport.py +0 -314
- agentirc_cli-8.7.1/tests/test_irc_transport_tags.py +0 -106
- agentirc_cli-8.7.1/tests/test_learn_prompt.py +0 -54
- agentirc_cli-8.7.1/tests/test_link_reconnect.py +0 -222
- agentirc_cli-8.7.1/tests/test_manifest_config.py +0 -317
- agentirc_cli-8.7.1/tests/test_mention_alias.py +0 -156
- agentirc_cli-8.7.1/tests/test_mention_target_cleanup.py +0 -135
- agentirc_cli-8.7.1/tests/test_mention_warning.py +0 -62
- agentirc_cli-8.7.1/tests/test_mentions.py +0 -155
- agentirc_cli-8.7.1/tests/test_mesh_config.py +0 -192
- agentirc_cli-8.7.1/tests/test_mesh_readiness.py +0 -93
- agentirc_cli-8.7.1/tests/test_message.py +0 -79
- agentirc_cli-8.7.1/tests/test_message_buffer.py +0 -71
- agentirc_cli-8.7.1/tests/test_message_tags.py +0 -75
- agentirc_cli-8.7.1/tests/test_messaging.py +0 -103
- agentirc_cli-8.7.1/tests/test_migrate_cli.py +0 -128
- agentirc_cli-8.7.1/tests/test_modes.py +0 -327
- agentirc_cli-8.7.1/tests/test_overview_cli.py +0 -137
- agentirc_cli-8.7.1/tests/test_overview_collector.py +0 -161
- agentirc_cli-8.7.1/tests/test_overview_model.py +0 -171
- agentirc_cli-8.7.1/tests/test_overview_renderer.py +0 -304
- agentirc_cli-8.7.1/tests/test_overview_web.py +0 -179
- agentirc_cli-8.7.1/tests/test_persistence.py +0 -105
- agentirc_cli-8.7.1/tests/test_persistence_timeout.py +0 -59
- agentirc_cli-8.7.1/tests/test_pidfile.py +0 -122
- agentirc_cli-8.7.1/tests/test_poll_loop.py +0 -129
- agentirc_cli-8.7.1/tests/test_register_cli.py +0 -139
- agentirc_cli-8.7.1/tests/test_room_persistence.py +0 -75
- agentirc_cli-8.7.1/tests/test_rooms.py +0 -729
- agentirc_cli-8.7.1/tests/test_rooms_federation.py +0 -63
- agentirc_cli-8.7.1/tests/test_rooms_integration.py +0 -110
- agentirc_cli-8.7.1/tests/test_server_icon_skill.py +0 -214
- agentirc_cli-8.7.1/tests/test_setup_update_cli.py +0 -185
- agentirc_cli-8.7.1/tests/test_skill_client.py +0 -96
- agentirc_cli-8.7.1/tests/test_skill_docs.py +0 -130
- agentirc_cli-8.7.1/tests/test_skills.py +0 -212
- agentirc_cli-8.7.1/tests/test_socket_path_convergence.py +0 -153
- agentirc_cli-8.7.1/tests/test_socket_server.py +0 -74
- agentirc_cli-8.7.1/tests/test_supervisor.py +0 -258
- agentirc_cli-8.7.1/tests/test_template_engine.py +0 -80
- agentirc_cli-8.7.1/tests/test_thread_buffer.py +0 -55
- agentirc_cli-8.7.1/tests/test_threads.py +0 -384
- agentirc_cli-8.7.1/tests/test_virtual_client.py +0 -176
- agentirc_cli-8.7.1/tests/test_wait_for_port.py +0 -89
- agentirc_cli-8.7.1/tests/test_webhook.py +0 -85
- agentirc_cli-8.7.1/tests/test_welcome_bot.py +0 -87
- agentirc_cli-8.7.1/uv.lock +0 -2717
- {agentirc_cli-8.7.1/culture/agentirc → agentirc_cli-9.0.0/tests}/__init__.py +0 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pr-review
|
|
3
|
+
description: >
|
|
4
|
+
PR workflow for agentirc: branch, commit, push, PR, wait for Qodo/Copilot,
|
|
5
|
+
triage, fix, reply, resolve. Includes a portability lint (no absolute /home
|
|
6
|
+
paths, no per-user dotfile refs in committed docs) and an alignment-delta
|
|
7
|
+
check when CLAUDE.md or anything under .claude/skills/ changes. Use when:
|
|
8
|
+
creating PRs, handling review feedback, or the user says "create PR",
|
|
9
|
+
"review comments", "address feedback", "resolve threads".
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# PR Review — agentirc edition
|
|
13
|
+
|
|
14
|
+
Vendored from `../steward/.claude/skills/pr-review/` per
|
|
15
|
+
`docs/steward/onboarding.md`. Re-sync explicitly when steward updates upstream
|
|
16
|
+
— there is no auto-sync.
|
|
17
|
+
|
|
18
|
+
agentirc's PRs touch the bootstrap spec, `CLAUDE.md`, vendored skills, and
|
|
19
|
+
(post-bootstrap) the IRCd server core. Two recurring bug classes the generic
|
|
20
|
+
`pr-review` skills miss:
|
|
21
|
+
|
|
22
|
+
- **Path leaks** — committing absolute home-directory paths that work only on
|
|
23
|
+
the author's machine.
|
|
24
|
+
- **Per-user config dependencies** — referencing a dotfile under the user's
|
|
25
|
+
home directory in repo guidance, breaking reproducibility for other
|
|
26
|
+
contributors and CI.
|
|
27
|
+
|
|
28
|
+
Both are caught by `scripts/portability-lint.sh`. The full workflow is
|
|
29
|
+
encapsulated in `scripts/workflow.sh` — follow that, not a manual checklist.
|
|
30
|
+
|
|
31
|
+
## Prerequisites
|
|
32
|
+
|
|
33
|
+
Hard requirements: `gh` (GitHub CLI), `jq`, `bash`, `python3` (stdlib only),
|
|
34
|
+
`curl` (used by `pr-status.sh`).
|
|
35
|
+
|
|
36
|
+
Per-machine paths (sibling-project layout) live in
|
|
37
|
+
`.claude/skills.local.yaml`; see the committed `.example` for the schema.
|
|
38
|
+
|
|
39
|
+
## How to run
|
|
40
|
+
|
|
41
|
+
`scripts/workflow.sh` is the entry point. Subcommands:
|
|
42
|
+
|
|
43
|
+
| Command | Purpose |
|
|
44
|
+
|---------|---------|
|
|
45
|
+
| `workflow.sh lint` | Portability lint on the current diff (staged + unstaged). |
|
|
46
|
+
| `workflow.sh poll <PR>` | Fetch and display all review comments. |
|
|
47
|
+
| `workflow.sh delta` | Dump each sibling project's `CLAUDE.md` head + `culture.yaml`. |
|
|
48
|
+
| `workflow.sh reply <PR>` | Batch reply (JSONL on stdin) and resolve threads. |
|
|
49
|
+
| `workflow.sh help` | Print this list. |
|
|
50
|
+
|
|
51
|
+
The single-comment helpers — `pr-reply.sh`, `pr-status.sh` — live next to
|
|
52
|
+
`workflow.sh` and are usable directly when batching isn't appropriate.
|
|
53
|
+
|
|
54
|
+
## End-to-end flow
|
|
55
|
+
|
|
56
|
+
```text
|
|
57
|
+
git checkout -b <type>/<desc>
|
|
58
|
+
# ... edit ...
|
|
59
|
+
.claude/skills/pr-review/scripts/workflow.sh lint
|
|
60
|
+
git commit -am "..." && git push -u origin <branch>
|
|
61
|
+
gh pr create --title "..." --body "..." # title <70 chars, body signed "- Claude"
|
|
62
|
+
sleep 300 # wait for Qodo + Copilot
|
|
63
|
+
.claude/skills/pr-review/scripts/workflow.sh poll <PR>
|
|
64
|
+
# triage; if CLAUDE.md / .claude/skills changed:
|
|
65
|
+
.claude/skills/pr-review/scripts/workflow.sh delta
|
|
66
|
+
# fix, re-lint, push
|
|
67
|
+
.claude/skills/pr-review/scripts/workflow.sh reply <PR> < replies.jsonl
|
|
68
|
+
gh pr checks <PR>
|
|
69
|
+
# Wait for human merge — never merge yourself.
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Branch naming: `fix/<desc>`, `feat/<desc>`, `docs/<desc>`, `skill/<name>`.
|
|
73
|
+
Commit/PR signature: `- Claude` (workspace convention). The reply script
|
|
74
|
+
auto-appends `- Claude` only if the body isn't already signed, so JSONL
|
|
75
|
+
entries can include or omit it.
|
|
76
|
+
|
|
77
|
+
## Triage rules
|
|
78
|
+
|
|
79
|
+
For every comment, decide **FIX** or **PUSHBACK** with reasoning.
|
|
80
|
+
|
|
81
|
+
Default to **FIX** for: portability complaints (always valid — recurring bug
|
|
82
|
+
class), test or doc requests, style nits aligned with workspace conventions,
|
|
83
|
+
and inconsistencies the reviewer catches between spec sections.
|
|
84
|
+
|
|
85
|
+
Default to **PUSHBACK** for: architecture opinions that conflict with
|
|
86
|
+
`CLAUDE.md` or the bootstrap spec; greenfield false-positives (e.g. "add
|
|
87
|
+
tests" before there's any source — defer to a later PR with a clear note,
|
|
88
|
+
don't refuse).
|
|
89
|
+
|
|
90
|
+
### Alignment-delta rule
|
|
91
|
+
|
|
92
|
+
If the PR touches `CLAUDE.md` or anything under `.claude/skills/`, run
|
|
93
|
+
`workflow.sh delta` **before** declaring FIX or PUSHBACK on each comment.
|
|
94
|
+
The script dumps the head of every sibling project's `CLAUDE.md` plus the
|
|
95
|
+
full `culture.yaml`, using `sibling_projects` from `skills.local.yaml`.
|
|
96
|
+
agentirc's siblings are `culture` and `steward` — note any sibling that
|
|
97
|
+
needs a follow-up PR and mention it in your reply.
|
|
98
|
+
|
|
99
|
+
## Greenfield-aware steps
|
|
100
|
+
|
|
101
|
+
The lint and the workflow script are always-on. Stack-specific steps are
|
|
102
|
+
conditional and currently no-op (greenfield repo until the bootstrap lands):
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
[ -d tests ] && [ -f pyproject.toml ] && uv run pytest tests/ -x -q
|
|
106
|
+
[ -f pyproject.toml ] && bump_version_per_project_convention
|
|
107
|
+
[ -f .markdownlint-cli2.yaml ] && markdownlint-cli2 "$(git diff --name-only --cached '*.md')"
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Revisit each line as the corresponding stack element actually lands during
|
|
111
|
+
or after the bootstrap.
|
|
112
|
+
|
|
113
|
+
## Reply etiquette
|
|
114
|
+
|
|
115
|
+
Every comment must get a reply — no silent fixes. Always pass `--resolve`
|
|
116
|
+
when batch-replying so threads close automatically. Reference the
|
|
117
|
+
review-comment IDs in the fix-up commit message. agentirc currently has no
|
|
118
|
+
SonarCloud project and isn't a registered mesh agent, so skip the
|
|
119
|
+
sonarclaude check and the post-merge IRC ping that culture's `pr-review`
|
|
120
|
+
includes — those will return when agentirc joins those systems (the
|
|
121
|
+
`sonarclaude` skill is on the steward-onboarding vendoring queue).
|
|
122
|
+
|
|
123
|
+
## All-backends rule
|
|
124
|
+
|
|
125
|
+
agentirc has no agent backends, so the all-backends rule that culture
|
|
126
|
+
enforces does not apply here. If a comment cites it, push back.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Portability lint: catch path leaks and per-user config dependencies in
|
|
3
|
+
# committed docs/configs before they ship in a PR.
|
|
4
|
+
#
|
|
5
|
+
# Usage: portability-lint.sh [--all]
|
|
6
|
+
# default: lint files modified vs HEAD (staged + unstaged)
|
|
7
|
+
# --all: lint all tracked files
|
|
8
|
+
#
|
|
9
|
+
# Exits 0 if clean, 1 if any leak is found.
|
|
10
|
+
|
|
11
|
+
set -euo pipefail
|
|
12
|
+
|
|
13
|
+
mode="${1:-diff}"
|
|
14
|
+
case "$mode" in
|
|
15
|
+
--all) files=$(git ls-files -- ':(exclude)*.lock') ;;
|
|
16
|
+
diff|--diff) files=$(git diff --diff-filter=AMR --name-only HEAD -- ':(exclude)*.lock') ;;
|
|
17
|
+
*) echo "Usage: $(basename "$0") [--all]" >&2; exit 2 ;;
|
|
18
|
+
esac
|
|
19
|
+
|
|
20
|
+
[ -z "$files" ] && { echo "(no files to check)"; exit 0; }
|
|
21
|
+
|
|
22
|
+
# ----- Check 1: hard-coded /home/<user>/... paths -----
|
|
23
|
+
hits1=$(echo "$files" | xargs -r grep -nE '/home/[a-z][a-z0-9_-]+/' 2>/dev/null || true)
|
|
24
|
+
|
|
25
|
+
# ----- Check 2: per-user dotfile *config* refs in committed docs/configs -----
|
|
26
|
+
# Carve-outs (allowed, NOT flagged):
|
|
27
|
+
# - ~/.claude/skills/<x>/scripts/ vendored tool calls
|
|
28
|
+
# - ~/.culture/ Culture mesh data this skill is supposed to read
|
|
29
|
+
md_yaml=$(echo "$files" | grep -E '\.(md|ya?ml|toml|json|jsonc)$' || true)
|
|
30
|
+
if [ -n "$md_yaml" ]; then
|
|
31
|
+
hits2=$(echo "$md_yaml" | xargs -r grep -nE '~/\.[A-Za-z]' 2>/dev/null \
|
|
32
|
+
| grep -vE '~/\.claude/skills/[^[:space:]"]+/scripts/' \
|
|
33
|
+
| grep -vE '~/\.culture/' \
|
|
34
|
+
|| true)
|
|
35
|
+
else
|
|
36
|
+
hits2=""
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
fail=0
|
|
40
|
+
if [ -n "$hits1" ]; then
|
|
41
|
+
echo "❌ Hard-coded /home/<user>/ paths:"
|
|
42
|
+
echo "$hits1" | sed 's/^/ /'
|
|
43
|
+
echo " Fix: use ../sibling, repo URL, or \$WORKSPACE/sibling instead."
|
|
44
|
+
fail=1
|
|
45
|
+
fi
|
|
46
|
+
if [ -n "$hits2" ]; then
|
|
47
|
+
[ "$fail" -eq 1 ] && echo
|
|
48
|
+
echo "❌ Per-user ~/.<dotfile> config refs in committed doc/config:"
|
|
49
|
+
echo "$hits2" | sed 's/^/ /'
|
|
50
|
+
echo " Allowed carve-outs: ~/.claude/skills/.../scripts/ (tool calls), ~/.culture/ (mesh data)."
|
|
51
|
+
echo " Otherwise: commit a repo-local config or document a portable lookup."
|
|
52
|
+
fail=1
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
[ "$fail" -eq 0 ] && echo "✓ portability lint clean ($(echo "$files" | wc -l | tr -d ' ') files checked)"
|
|
56
|
+
exit $fail
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# Batch reply to PR review comments from JSONL on stdin.
|
|
5
|
+
# Each line: {"comment_id": 123, "body": "reply text"}
|
|
6
|
+
# Usage: pr-batch.sh [--repo OWNER/REPO] [--resolve] PR_NUMBER < input.jsonl
|
|
7
|
+
|
|
8
|
+
REPO=""
|
|
9
|
+
RESOLVE=false
|
|
10
|
+
|
|
11
|
+
while [[ $# -gt 0 ]]; do
|
|
12
|
+
case "$1" in
|
|
13
|
+
--repo) REPO="$2"; shift 2 ;;
|
|
14
|
+
--resolve) RESOLVE=true; shift ;;
|
|
15
|
+
*) break ;;
|
|
16
|
+
esac
|
|
17
|
+
done
|
|
18
|
+
|
|
19
|
+
PR_NUMBER="${1:?Usage: pr-batch.sh [--repo OWNER/REPO] [--resolve] PR_NUMBER < input.jsonl}"
|
|
20
|
+
|
|
21
|
+
if [[ -z "$REPO" ]]; then
|
|
22
|
+
REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
26
|
+
RESOLVE_FLAG=""
|
|
27
|
+
if [[ "$RESOLVE" == true ]]; then
|
|
28
|
+
RESOLVE_FLAG="--resolve"
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
SUCCESS=0
|
|
32
|
+
FAIL=0
|
|
33
|
+
|
|
34
|
+
while IFS= read -r line; do
|
|
35
|
+
# Skip empty lines
|
|
36
|
+
[[ -z "$line" ]] && continue
|
|
37
|
+
|
|
38
|
+
COMMENT_ID=$(echo "$line" | jq -r '.comment_id')
|
|
39
|
+
BODY=$(echo "$line" | jq -r '.body')
|
|
40
|
+
|
|
41
|
+
if [[ "$COMMENT_ID" == "null" || "$BODY" == "null" ]]; then
|
|
42
|
+
echo "SKIP: invalid line: $line"
|
|
43
|
+
((FAIL++)) || true
|
|
44
|
+
continue
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
echo "--- Comment $COMMENT_ID ---"
|
|
48
|
+
if bash "$SCRIPT_DIR/pr-reply.sh" --repo "$REPO" $RESOLVE_FLAG "$PR_NUMBER" "$COMMENT_ID" "$BODY"; then
|
|
49
|
+
((SUCCESS++)) || true
|
|
50
|
+
else
|
|
51
|
+
echo "FAILED: comment $COMMENT_ID"
|
|
52
|
+
((FAIL++)) || true
|
|
53
|
+
fi
|
|
54
|
+
done
|
|
55
|
+
|
|
56
|
+
echo ""
|
|
57
|
+
echo "Done: $SUCCESS succeeded, $FAIL failed"
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# Fetch and display all PR feedback in one pass:
|
|
5
|
+
# 1. Inline review comments (with thread resolve status)
|
|
6
|
+
# 2. Issue comments (qodo summaries, sonarcloud, etc.)
|
|
7
|
+
# 3. Top-level reviews with a non-empty body (copilot overview, etc.)
|
|
8
|
+
#
|
|
9
|
+
# Usage: pr-comments.sh [--repo OWNER/REPO] PR_NUMBER
|
|
10
|
+
|
|
11
|
+
REPO=""
|
|
12
|
+
|
|
13
|
+
while [[ $# -gt 0 ]]; do
|
|
14
|
+
case "$1" in
|
|
15
|
+
--repo) REPO="$2"; shift 2 ;;
|
|
16
|
+
*) break ;;
|
|
17
|
+
esac
|
|
18
|
+
done
|
|
19
|
+
|
|
20
|
+
PR_NUMBER="${1:?Usage: pr-comments.sh [--repo OWNER/REPO] PR_NUMBER}"
|
|
21
|
+
|
|
22
|
+
if [[ -z "$REPO" ]]; then
|
|
23
|
+
REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
# ── Section 1: inline review comments ─────────────────────────────────────
|
|
27
|
+
THREADS_JSON=$(gh api graphql -f query="
|
|
28
|
+
{
|
|
29
|
+
repository(owner: \"${REPO%%/*}\", name: \"${REPO##*/}\") {
|
|
30
|
+
pullRequest(number: $PR_NUMBER) {
|
|
31
|
+
reviewThreads(first: 100) {
|
|
32
|
+
nodes {
|
|
33
|
+
id
|
|
34
|
+
isResolved
|
|
35
|
+
comments(first: 100) {
|
|
36
|
+
nodes { databaseId }
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}" --jq '.data.repository.pullRequest.reviewThreads.nodes')
|
|
43
|
+
|
|
44
|
+
# Build a map from every comment ID in every thread → its thread metadata,
|
|
45
|
+
# so replies in a thread also show resolved status (not just the first comment).
|
|
46
|
+
THREAD_MAP=$(echo "$THREADS_JSON" | jq -r '
|
|
47
|
+
[.[] as $t | $t.comments.nodes[] | {
|
|
48
|
+
comment_id: .databaseId,
|
|
49
|
+
thread_id: $t.id,
|
|
50
|
+
resolved: $t.isResolved
|
|
51
|
+
}]
|
|
52
|
+
')
|
|
53
|
+
|
|
54
|
+
INLINE=$(gh api "repos/$REPO/pulls/$PR_NUMBER/comments" --paginate)
|
|
55
|
+
INLINE_COUNT=$(echo "$INLINE" | jq 'length')
|
|
56
|
+
|
|
57
|
+
echo "════════════════ INLINE REVIEW COMMENTS ($INLINE_COUNT) ════════════════"
|
|
58
|
+
echo "$INLINE" | jq -r --argjson threads "$THREAD_MAP" '
|
|
59
|
+
.[] | . as $c |
|
|
60
|
+
($threads | map(select(.comment_id == $c.id)) | first // {resolved: "unknown", thread_id: "?"}) as $t |
|
|
61
|
+
"──────────────────────────────────────────────────",
|
|
62
|
+
"ID: \($c.id) | Thread: \(if $t.resolved == true then "RESOLVED" elif $t.resolved == false then "UNRESOLVED" else "?" end) | Reply-to: \($c.in_reply_to_id // "none")",
|
|
63
|
+
"File: \($c.path):\($c.original_line // $c.line // "?")",
|
|
64
|
+
"Thread ID: \($t.thread_id)",
|
|
65
|
+
"Author: \($c.user.login)",
|
|
66
|
+
"",
|
|
67
|
+
($c.body | split("\n") | if length > 10 then .[:10] + ["... (truncated)"] else . end | join("\n")),
|
|
68
|
+
""
|
|
69
|
+
'
|
|
70
|
+
|
|
71
|
+
# ── Section 2: issue comments (general PR comments) ───────────────────────
|
|
72
|
+
ISSUE=$(gh api "repos/$REPO/issues/$PR_NUMBER/comments" --paginate)
|
|
73
|
+
ISSUE_COUNT=$(echo "$ISSUE" | jq 'length')
|
|
74
|
+
|
|
75
|
+
echo ""
|
|
76
|
+
echo "════════════════ ISSUE COMMENTS ($ISSUE_COUNT) ════════════════"
|
|
77
|
+
echo "$ISSUE" | jq -r '
|
|
78
|
+
.[] |
|
|
79
|
+
"──────────────────────────────────────────────────",
|
|
80
|
+
"ID: \(.id) | Author: \(.user.login) | Created: \(.created_at)",
|
|
81
|
+
"",
|
|
82
|
+
(.body | split("\n") | if length > 10 then .[:10] + ["... (truncated)"] else . end | join("\n")),
|
|
83
|
+
""
|
|
84
|
+
'
|
|
85
|
+
|
|
86
|
+
# ── Section 3: top-level reviews with a body ──────────────────────────────
|
|
87
|
+
REVIEWS=$(gh api "repos/$REPO/pulls/$PR_NUMBER/reviews" --paginate)
|
|
88
|
+
REVIEWS_WITH_BODY=$(echo "$REVIEWS" | jq '[.[] | select((.body // "") != "")]')
|
|
89
|
+
REVIEW_COUNT=$(echo "$REVIEWS_WITH_BODY" | jq 'length')
|
|
90
|
+
|
|
91
|
+
echo ""
|
|
92
|
+
echo "════════════════ TOP-LEVEL REVIEWS ($REVIEW_COUNT) ════════════════"
|
|
93
|
+
echo "$REVIEWS_WITH_BODY" | jq -r '
|
|
94
|
+
.[] |
|
|
95
|
+
"──────────────────────────────────────────────────",
|
|
96
|
+
"Review ID: \(.id) | Author: \(.user.login) | State: \(.state) | Submitted: \(.submitted_at)",
|
|
97
|
+
"",
|
|
98
|
+
(.body | split("\n") | if length > 10 then .[:10] + ["... (truncated)"] else . end | join("\n")),
|
|
99
|
+
""
|
|
100
|
+
'
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# Reply to a PR review comment, optionally resolve its thread.
|
|
5
|
+
# Usage: pr-reply.sh [--repo OWNER/REPO] [--resolve] PR_NUMBER COMMENT_ID "body"
|
|
6
|
+
|
|
7
|
+
REPO=""
|
|
8
|
+
RESOLVE=false
|
|
9
|
+
|
|
10
|
+
while [[ $# -gt 0 ]]; do
|
|
11
|
+
case "$1" in
|
|
12
|
+
--repo) REPO="$2"; shift 2 ;;
|
|
13
|
+
--resolve) RESOLVE=true; shift ;;
|
|
14
|
+
*) break ;;
|
|
15
|
+
esac
|
|
16
|
+
done
|
|
17
|
+
|
|
18
|
+
PR_NUMBER="${1:?Usage: pr-reply.sh [--repo OWNER/REPO] [--resolve] PR_NUMBER COMMENT_ID \"body\"}"
|
|
19
|
+
COMMENT_ID="${2:?Missing COMMENT_ID}"
|
|
20
|
+
BODY="${3:?Missing reply body}"
|
|
21
|
+
|
|
22
|
+
if [[ -z "$REPO" ]]; then
|
|
23
|
+
REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
# Append signature only if the body isn't already signed.
|
|
27
|
+
if ! printf '%s' "$BODY" | grep -qE '(^|\n)[[:space:]]*-[[:space:]]+Claude[[:space:]]*$'; then
|
|
28
|
+
BODY="${BODY}
|
|
29
|
+
|
|
30
|
+
- Claude"
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
# Post reply
|
|
34
|
+
REPLY_URL=$(gh api "repos/$REPO/pulls/$PR_NUMBER/comments/$COMMENT_ID/replies" \
|
|
35
|
+
-f body="$BODY" \
|
|
36
|
+
--jq '.html_url')
|
|
37
|
+
echo "Replied: $REPLY_URL"
|
|
38
|
+
|
|
39
|
+
# Resolve thread if requested
|
|
40
|
+
if [[ "$RESOLVE" == true ]]; then
|
|
41
|
+
# Find the thread ID for this comment
|
|
42
|
+
THREAD_ID=$(gh api graphql -f query="
|
|
43
|
+
{
|
|
44
|
+
repository(owner: \"${REPO%%/*}\", name: \"${REPO##*/}\") {
|
|
45
|
+
pullRequest(number: $PR_NUMBER) {
|
|
46
|
+
reviewThreads(first: 100) {
|
|
47
|
+
nodes {
|
|
48
|
+
id
|
|
49
|
+
comments(first: 100) {
|
|
50
|
+
nodes { databaseId }
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}" --jq ".data.repository.pullRequest.reviewThreads.nodes[] | select(any(.comments.nodes[]; .databaseId == $COMMENT_ID)) | .id")
|
|
57
|
+
|
|
58
|
+
if [[ -n "$THREAD_ID" ]]; then
|
|
59
|
+
RESOLVED=$(gh api graphql -f query="
|
|
60
|
+
mutation { resolveReviewThread(input: {threadId: \"$THREAD_ID\"}) { thread { isResolved } } }
|
|
61
|
+
" --jq '.data.resolveReviewThread.thread.isResolved')
|
|
62
|
+
echo "Resolved: $RESOLVED (thread $THREAD_ID)"
|
|
63
|
+
else
|
|
64
|
+
echo "Warning: could not find thread for comment $COMMENT_ID"
|
|
65
|
+
fi
|
|
66
|
+
fi
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# pr-status.sh — one-shot status overview for a PR.
|
|
3
|
+
#
|
|
4
|
+
# Combines five things review feedback usually scatters across:
|
|
5
|
+
# 1. PR state (open / merged / closed) + branch + author
|
|
6
|
+
# 2. CI checks (build / lint / unit / sonarcloud / cf-pages / etc.)
|
|
7
|
+
# 3. Review-bot pipeline status (Copilot, qodo, SonarCloud, Cloudflare)
|
|
8
|
+
# 4. SonarCloud quality gate + open-issue count
|
|
9
|
+
# 5. Inline-thread resolved-vs-unresolved tally
|
|
10
|
+
#
|
|
11
|
+
# Usage: scripts/pr-status.sh [--repo OWNER/REPO] [--sonar-key KEY] PR_NUMBER
|
|
12
|
+
#
|
|
13
|
+
# Defaults:
|
|
14
|
+
# --repo auto-detected via `gh repo view`
|
|
15
|
+
# --sonar-key derived from repo as `<owner>_<name>` (SonarCloud convention)
|
|
16
|
+
#
|
|
17
|
+
# Requires: gh, jq, curl, python3.
|
|
18
|
+
|
|
19
|
+
set -euo pipefail
|
|
20
|
+
|
|
21
|
+
REPO=""
|
|
22
|
+
SONAR_KEY=""
|
|
23
|
+
|
|
24
|
+
while [[ $# -gt 0 ]]; do
|
|
25
|
+
case "$1" in
|
|
26
|
+
--repo) REPO="$2"; shift 2 ;;
|
|
27
|
+
--sonar-key) SONAR_KEY="$2"; shift 2 ;;
|
|
28
|
+
*) break ;;
|
|
29
|
+
esac
|
|
30
|
+
done
|
|
31
|
+
|
|
32
|
+
PR_NUMBER="${1:?Usage: pr-status.sh [--repo OWNER/REPO] [--sonar-key KEY] PR_NUMBER}"
|
|
33
|
+
|
|
34
|
+
if [[ -z "$REPO" ]]; then
|
|
35
|
+
REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)
|
|
36
|
+
fi
|
|
37
|
+
if [[ -z "$SONAR_KEY" ]]; then
|
|
38
|
+
SONAR_KEY="${REPO%%/*}_${REPO##*/}"
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
# ── 1. PR header ──────────────────────────────────────────────────────────
|
|
42
|
+
PR_JSON=$(gh pr view "$PR_NUMBER" --json \
|
|
43
|
+
number,title,state,isDraft,mergedAt,mergedBy,baseRefName,headRefName,author,url)
|
|
44
|
+
|
|
45
|
+
echo "════════════════════════════════════════════════════════════════════"
|
|
46
|
+
echo "$PR_JSON" | jq -r '
|
|
47
|
+
"PR #\(.number) — \(.title)",
|
|
48
|
+
" \(.url)",
|
|
49
|
+
" Author: \(.author.login)",
|
|
50
|
+
" Branch: \(.headRefName) → \(.baseRefName)",
|
|
51
|
+
" State: \(if .state == "MERGED" then "MERGED at \(.mergedAt) by \(.mergedBy.login)" elif .state == "OPEN" and .isDraft then "OPEN (draft)" else .state end)"
|
|
52
|
+
'
|
|
53
|
+
echo "════════════════════════════════════════════════════════════════════"
|
|
54
|
+
|
|
55
|
+
# ── 2. CI checks ──────────────────────────────────────────────────────────
|
|
56
|
+
echo
|
|
57
|
+
echo "── CI checks ─────────────────────────────────────────────────────────"
|
|
58
|
+
# `gh pr checks` exits non-zero when checks are still pending/failing.
|
|
59
|
+
# We don't care about its exit code here; capture and pretty-print.
|
|
60
|
+
CHECKS=$(gh pr checks "$PR_NUMBER" 2>/dev/null || true)
|
|
61
|
+
if [[ -z "$CHECKS" ]]; then
|
|
62
|
+
echo " (no checks reported)"
|
|
63
|
+
else
|
|
64
|
+
echo "$CHECKS" | awk -F'\t' '
|
|
65
|
+
{
|
|
66
|
+
name = $1
|
|
67
|
+
state = $2
|
|
68
|
+
dur = $3
|
|
69
|
+
sym = "?"
|
|
70
|
+
if (state == "pass") sym = "✅"
|
|
71
|
+
else if (state == "fail") sym = "❌"
|
|
72
|
+
else if (state == "skipping") sym = "⏭"
|
|
73
|
+
else if (state == "pending" || state == "queued" || state == "in_progress") sym = "…"
|
|
74
|
+
printf " %s %-22s %-10s %s\n", sym, name, state, dur
|
|
75
|
+
}
|
|
76
|
+
'
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
# ── 3. Review bots & comment pipeline ────────────────────────────────────
|
|
80
|
+
echo
|
|
81
|
+
echo "── Review pipeline ───────────────────────────────────────────────────"
|
|
82
|
+
|
|
83
|
+
# Inline-thread tally via GraphQL (resolved vs unresolved).
|
|
84
|
+
THREADS_JSON=$(gh api graphql -f query="
|
|
85
|
+
{
|
|
86
|
+
repository(owner: \"${REPO%%/*}\", name: \"${REPO##*/}\") {
|
|
87
|
+
pullRequest(number: $PR_NUMBER) {
|
|
88
|
+
reviewThreads(first: 100) {
|
|
89
|
+
nodes { id isResolved comments(first: 1) { nodes { author { login } } } }
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}" --jq '.data.repository.pullRequest.reviewThreads.nodes')
|
|
94
|
+
|
|
95
|
+
INLINE_TOTAL=$(echo "$THREADS_JSON" | jq 'length')
|
|
96
|
+
INLINE_RESOLVED=$(echo "$THREADS_JSON" | jq '[.[] | select(.isResolved)] | length')
|
|
97
|
+
INLINE_PENDING=$((INLINE_TOTAL - INLINE_RESOLVED))
|
|
98
|
+
|
|
99
|
+
# Per-bot inline counts.
|
|
100
|
+
COPILOT_INLINE=$(echo "$THREADS_JSON" | jq '[.[] | select((.comments.nodes[0].author.login // "") | startswith("Copilot"))] | length')
|
|
101
|
+
QODO_INLINE=$(echo "$THREADS_JSON" | jq '[.[] | select((.comments.nodes[0].author.login // "") | startswith("qodo"))] | length')
|
|
102
|
+
|
|
103
|
+
# Issue-level comments (qodo summary, sonarcloud quality-gate body, cf-pages preview, etc.).
|
|
104
|
+
# Skip --paginate to avoid array concatenation; per_page=100 covers typical PRs.
|
|
105
|
+
ISSUE=$(gh api "repos/$REPO/issues/$PR_NUMBER/comments?per_page=100")
|
|
106
|
+
QODO_ISSUE=$(echo "$ISSUE" | jq '[.[] | select((.user.login // "") | startswith("qodo"))] | length')
|
|
107
|
+
SONARQUBE_ISSUE=$(echo "$ISSUE" | jq '[.[] | select((.user.login // "") | startswith("sonarqubecloud"))] | length')
|
|
108
|
+
CFPAGES_ISSUE=$(echo "$ISSUE" | jq '[.[] | select((.user.login // "") | test("cloudflare"))] | length')
|
|
109
|
+
COPILOT_TOPLEVEL=$(gh api "repos/$REPO/pulls/$PR_NUMBER/reviews?per_page=100" \
|
|
110
|
+
| jq '[.[] | select((.user.login // "") | startswith("copilot")) | select((.body // "") != "")] | length')
|
|
111
|
+
|
|
112
|
+
# Cloudflare deploy URL hidden in issue-comment bodies (look for pages.dev).
|
|
113
|
+
CF_URL=$(echo "$ISSUE" | jq -r '[.[].body // "" | scan("https?://[a-z0-9.-]+\\.pages\\.dev[^\\s)\"<]*")] | first // ""')
|
|
114
|
+
|
|
115
|
+
printf " %-12s %s\n" "Copilot" "$([[ "$COPILOT_TOPLEVEL" -gt 0 || "$COPILOT_INLINE" -gt 0 ]] && echo "✅ overview×$COPILOT_TOPLEVEL, inline×$COPILOT_INLINE" || echo "— no posts yet")"
|
|
116
|
+
printf " %-12s %s\n" "qodo" "$([[ "$QODO_ISSUE" -gt 0 || "$QODO_INLINE" -gt 0 ]] && echo "✅ summary×$QODO_ISSUE, inline×$QODO_INLINE" || echo "— no posts yet")"
|
|
117
|
+
printf " %-12s %s\n" "Cloudflare" "$([[ -n "$CF_URL" ]] && echo "✅ $CF_URL" || ([[ "$CFPAGES_ISSUE" -gt 0 ]] && echo "✅ ($CFPAGES_ISSUE comments)" || echo "— no deploy preview"))"
|
|
118
|
+
|
|
119
|
+
# ── 4. SonarCloud quality gate + open issues ─────────────────────────────
|
|
120
|
+
SONAR_QG=$(curl -s "https://sonarcloud.io/api/qualitygates/project_status?projectKey=${SONAR_KEY}&pullRequest=${PR_NUMBER}")
|
|
121
|
+
SONAR_QG_STATUS=$(echo "$SONAR_QG" | jq -r '.projectStatus.status // "UNKNOWN"')
|
|
122
|
+
SONAR_OPEN=$(curl -s "https://sonarcloud.io/api/issues/search?componentKeys=${SONAR_KEY}&pullRequest=${PR_NUMBER}&statuses=OPEN,CONFIRMED&ps=1" \
|
|
123
|
+
| jq -r '.total // 0')
|
|
124
|
+
SONAR_HOTSPOTS=$(curl -s "https://sonarcloud.io/api/hotspots/search?projectKey=${SONAR_KEY}&pullRequest=${PR_NUMBER}&status=TO_REVIEW&ps=1" \
|
|
125
|
+
| jq -r '.paging.total // 0')
|
|
126
|
+
|
|
127
|
+
case "$SONAR_QG_STATUS" in
|
|
128
|
+
OK) SONAR_SYM="✅" ;;
|
|
129
|
+
ERROR) SONAR_SYM="❌" ;;
|
|
130
|
+
WARN) SONAR_SYM="⚠ " ;;
|
|
131
|
+
*) SONAR_SYM="?" ;;
|
|
132
|
+
esac
|
|
133
|
+
printf " %-12s %s Quality Gate %s, %d OPEN issue(s), %d hotspot(s)\n" \
|
|
134
|
+
"SonarCloud" "$SONAR_SYM" "$SONAR_QG_STATUS" "$SONAR_OPEN" "$SONAR_HOTSPOTS"
|
|
135
|
+
|
|
136
|
+
# When SonarCloud has OPEN issues, list them — saves a follow-up curl.
|
|
137
|
+
if [[ "$SONAR_OPEN" != "0" ]]; then
|
|
138
|
+
echo
|
|
139
|
+
echo " SonarCloud OPEN issues:"
|
|
140
|
+
curl -s "https://sonarcloud.io/api/issues/search?componentKeys=${SONAR_KEY}&pullRequest=${PR_NUMBER}&statuses=OPEN,CONFIRMED&ps=20" \
|
|
141
|
+
| jq -r '.issues[] | " • [\(.rule)] \(.component | sub("^[^:]+:"; ""))(:\(.line // "?")) (\(.severity)) — \(.message)"'
|
|
142
|
+
fi
|
|
143
|
+
|
|
144
|
+
# ── 5. Tally + summary ────────────────────────────────────────────────────
|
|
145
|
+
echo
|
|
146
|
+
echo "── Inline threads ────────────────────────────────────────────────────"
|
|
147
|
+
printf " Total: %d Resolved: %d Unresolved: %d\n" \
|
|
148
|
+
"$INLINE_TOTAL" "$INLINE_RESOLVED" "$INLINE_PENDING"
|
|
149
|
+
|
|
150
|
+
if [[ "$INLINE_PENDING" -gt 0 ]]; then
|
|
151
|
+
echo
|
|
152
|
+
echo " Unresolved threads:"
|
|
153
|
+
echo "$THREADS_JSON" | jq -r '
|
|
154
|
+
.[] | select(.isResolved == false) |
|
|
155
|
+
" • \(.comments.nodes[0].author.login): thread \(.id)"
|
|
156
|
+
'
|
|
157
|
+
fi
|
|
158
|
+
|
|
159
|
+
echo
|
|
160
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
161
|
+
echo "(For full comment bodies: bash \"$SCRIPT_DIR/pr-comments.sh\" $PR_NUMBER)"
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# pr-review workflow entry point.
|
|
3
|
+
#
|
|
4
|
+
# Subcommands:
|
|
5
|
+
# lint run the portability lint on the current diff (staged + unstaged)
|
|
6
|
+
# poll <PR> fetch and display review comments
|
|
7
|
+
# reply <PR> batch reply to review comments (JSONL on stdin), --resolve
|
|
8
|
+
# delta dump CLAUDE.md head + culture.yaml for each sibling project
|
|
9
|
+
# listed in skills.local.yaml (alignment-delta check)
|
|
10
|
+
# help print this message
|
|
11
|
+
|
|
12
|
+
set -euo pipefail
|
|
13
|
+
|
|
14
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
15
|
+
SKILL_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
16
|
+
REPO_ROOT="$(cd "$SKILL_DIR/../../.." && pwd)"
|
|
17
|
+
|
|
18
|
+
CFG="$REPO_ROOT/.claude/skills.local.yaml"
|
|
19
|
+
[ -f "$CFG" ] || CFG="$REPO_ROOT/.claude/skills.local.yaml.example"
|
|
20
|
+
|
|
21
|
+
# Read a top-level YAML list from CFG. Schema is intentionally tiny:
|
|
22
|
+
# <key>:
|
|
23
|
+
# - item
|
|
24
|
+
# - item
|
|
25
|
+
# Stops at the next top-level key. No PyYAML dependency.
|
|
26
|
+
read_list() {
|
|
27
|
+
awk -v key="$1" '
|
|
28
|
+
function trim(s) { sub(/^[[:space:]]+/, "", s); sub(/[[:space:]]+$/, "", s); return s }
|
|
29
|
+
{
|
|
30
|
+
line = $0
|
|
31
|
+
sub(/[[:space:]]+#.*$/, "", line)
|
|
32
|
+
}
|
|
33
|
+
in_list && line ~ /^[[:space:]]*-[[:space:]]*/ {
|
|
34
|
+
item = line
|
|
35
|
+
sub(/^[[:space:]]*-[[:space:]]*/, "", item)
|
|
36
|
+
item = trim(item)
|
|
37
|
+
sub(/^["\047]/, "", item); sub(/["\047]$/, "", item)
|
|
38
|
+
if (item != "") print item
|
|
39
|
+
next
|
|
40
|
+
}
|
|
41
|
+
in_list && line ~ /^[^[:space:]#]/ { exit }
|
|
42
|
+
line ~ ("^" key ":[[:space:]]*($|#)") { in_list = 1 }
|
|
43
|
+
' "$CFG"
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
cmd="${1:-help}"
|
|
47
|
+
shift || true
|
|
48
|
+
|
|
49
|
+
case "$cmd" in
|
|
50
|
+
lint)
|
|
51
|
+
bash "$SCRIPT_DIR/portability-lint.sh"
|
|
52
|
+
;;
|
|
53
|
+
poll)
|
|
54
|
+
PR="${1:?Usage: workflow.sh poll <PR>}"
|
|
55
|
+
bash "$SCRIPT_DIR/pr-comments.sh" "$PR"
|
|
56
|
+
;;
|
|
57
|
+
reply)
|
|
58
|
+
PR="${1:?Usage: workflow.sh reply <PR> (JSONL on stdin)}"
|
|
59
|
+
bash "$SCRIPT_DIR/pr-batch.sh" --resolve "$PR"
|
|
60
|
+
;;
|
|
61
|
+
delta)
|
|
62
|
+
any=0
|
|
63
|
+
while IFS= read -r sibling; do
|
|
64
|
+
[ -z "$sibling" ] && continue
|
|
65
|
+
any=1
|
|
66
|
+
sibling_abs="$REPO_ROOT/$sibling"
|
|
67
|
+
if [ ! -d "$sibling_abs" ] && [ ! -d "$sibling" ]; then
|
|
68
|
+
echo "=== $sibling ==="
|
|
69
|
+
echo "(not present on disk — skipped)"
|
|
70
|
+
continue
|
|
71
|
+
fi
|
|
72
|
+
target="$sibling_abs"
|
|
73
|
+
[ -d "$target" ] || target="$sibling"
|
|
74
|
+
echo "=== $target ==="
|
|
75
|
+
if [ -f "$target/CLAUDE.md" ]; then
|
|
76
|
+
head -40 "$target/CLAUDE.md"
|
|
77
|
+
echo "..."
|
|
78
|
+
else
|
|
79
|
+
echo "(no CLAUDE.md)"
|
|
80
|
+
fi
|
|
81
|
+
echo "--- culture.yaml ---"
|
|
82
|
+
if [ -f "$target/culture.yaml" ]; then
|
|
83
|
+
cat "$target/culture.yaml"
|
|
84
|
+
else
|
|
85
|
+
echo "(no culture.yaml)"
|
|
86
|
+
fi
|
|
87
|
+
echo
|
|
88
|
+
done < <(read_list sibling_projects)
|
|
89
|
+
[ "$any" -eq 0 ] && echo "(no sibling_projects configured in $CFG)"
|
|
90
|
+
;;
|
|
91
|
+
help|--help|-h)
|
|
92
|
+
sed -n '2,11p' "${BASH_SOURCE[0]}" | sed 's/^# *//'
|
|
93
|
+
;;
|
|
94
|
+
*)
|
|
95
|
+
echo "unknown subcommand: $cmd" >&2
|
|
96
|
+
echo "run '$(basename "$0") help' for usage." >&2
|
|
97
|
+
exit 2
|
|
98
|
+
;;
|
|
99
|
+
esac
|