agentirc-cli 9.6.1__tar.gz → 9.7.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. agentirc_cli-9.7.0/.claude/skills/assign-to-workforce/SKILL.md +243 -0
  2. agentirc_cli-9.7.0/.claude/skills/assign-to-workforce/scripts/assign-to-workforce.sh +213 -0
  3. agentirc_cli-9.7.0/.claude/skills/cicd/SKILL.md +196 -0
  4. agentirc_cli-9.7.0/.claude/skills/cicd/scripts/_resolve-nick.sh +43 -0
  5. {agentirc_cli-9.6.1/.claude/skills/pr-review → agentirc_cli-9.7.0/.claude/skills/cicd}/scripts/portability-lint.sh +2 -1
  6. {agentirc_cli-9.6.1/.claude/skills/pr-review → agentirc_cli-9.7.0/.claude/skills/cicd}/scripts/pr-reply.sh +16 -5
  7. {agentirc_cli-9.6.1/.claude/skills/pr-review → agentirc_cli-9.7.0/.claude/skills/cicd}/scripts/pr-status.sh +6 -4
  8. agentirc_cli-9.7.0/.claude/skills/cicd/scripts/workflow.sh +157 -0
  9. agentirc_cli-9.7.0/.claude/skills/communicate/SKILL.md +255 -0
  10. agentirc_cli-9.7.0/.claude/skills/communicate/scripts/fetch-issues.sh +59 -0
  11. agentirc_cli-9.7.0/.claude/skills/communicate/scripts/mesh-message.sh +74 -0
  12. agentirc_cli-9.7.0/.claude/skills/communicate/scripts/post-comment.sh +65 -0
  13. agentirc_cli-9.7.0/.claude/skills/communicate/scripts/post-issue.sh +71 -0
  14. agentirc_cli-9.7.0/.claude/skills/spec-to-plan/SKILL.md +230 -0
  15. agentirc_cli-9.7.0/.claude/skills/spec-to-plan/scripts/spec-to-plan.sh +102 -0
  16. agentirc_cli-9.7.0/.claude/skills/think/SKILL.md +203 -0
  17. agentirc_cli-9.7.0/.claude/skills/think/scripts/think.sh +101 -0
  18. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/.claude/skills.local.yaml.example +1 -1
  19. agentirc_cli-9.7.0/.devague/current +1 -0
  20. agentirc_cli-9.7.0/.devague/current_plan +1 -0
  21. agentirc_cli-9.7.0/.devague/frames/agentirc-9-7-0-ships-an-embedded-bot-framework-bot.json +211 -0
  22. agentirc_cli-9.7.0/.devague/plans/agentirc-9-7-0-ships-an-embedded-bot-framework-bot.json +318 -0
  23. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/.github/workflows/tests.yml +1 -1
  24. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/.gitignore +3 -0
  25. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/CHANGELOG.md +76 -0
  26. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/CLAUDE.md +12 -8
  27. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/PKG-INFO +8 -3
  28. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/README.md +4 -2
  29. agentirc_cli-9.7.0/agentirc/_internal/bots/bot_manager.py +33 -0
  30. agentirc_cli-9.7.0/agentirc/_internal/bots/http_listener.py +33 -0
  31. agentirc_cli-9.7.0/agentirc/bots/__init__.py +30 -0
  32. agentirc_cli-9.7.0/agentirc/bots/bot.py +269 -0
  33. agentirc_cli-9.7.0/agentirc/bots/bot_manager.py +347 -0
  34. agentirc_cli-9.7.0/agentirc/bots/cli.py +331 -0
  35. agentirc_cli-9.7.0/agentirc/bots/config.py +199 -0
  36. agentirc_cli-9.7.0/agentirc/bots/filter_dsl.py +339 -0
  37. agentirc_cli-9.7.0/agentirc/bots/http_listener.py +131 -0
  38. agentirc_cli-9.7.0/agentirc/bots/template_engine.py +68 -0
  39. agentirc_cli-9.7.0/agentirc/bots/virtual_client.py +29 -0
  40. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/cli.py +10 -0
  41. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/ircd.py +14 -11
  42. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/docs/api-stability.md +122 -2
  43. agentirc_cli-9.7.0/docs/plans/2026-06-12-agentirc-9-7-0-ships-an-embedded-bot-framework-bot.md +86 -0
  44. agentirc_cli-9.7.0/docs/specs/2026-06-12-agentirc-9-7-0-ships-an-embedded-bot-framework-bot.md +50 -0
  45. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/docs/steward/onboarding.md +5 -4
  46. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/pyproject.toml +52 -1
  47. agentirc_cli-9.7.0/tests/bots/test_bot.py +309 -0
  48. agentirc_cli-9.7.0/tests/bots/test_bot_host.py +77 -0
  49. agentirc_cli-9.7.0/tests/bots/test_bot_manager.py +302 -0
  50. agentirc_cli-9.7.0/tests/bots/test_cli_bot.py +272 -0
  51. agentirc_cli-9.7.0/tests/bots/test_config_bots.py +204 -0
  52. agentirc_cli-9.7.0/tests/bots/test_filter_dsl.py +260 -0
  53. agentirc_cli-9.7.0/tests/bots/test_http_listener.py +205 -0
  54. agentirc_cli-9.7.0/tests/bots/test_public_surface.py +168 -0
  55. agentirc_cli-9.7.0/tests/bots/test_template_engine.py +86 -0
  56. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/conftest.py +23 -0
  57. agentirc_cli-9.7.0/tests/telemetry/__init__.py +0 -0
  58. agentirc_cli-9.7.0/uv.lock +1473 -0
  59. agentirc_cli-9.6.1/.claude/skills/pr-review/SKILL.md +0 -126
  60. agentirc_cli-9.6.1/.claude/skills/pr-review/scripts/pr-batch.sh +0 -57
  61. agentirc_cli-9.6.1/.claude/skills/pr-review/scripts/pr-comments.sh +0 -100
  62. agentirc_cli-9.6.1/.claude/skills/pr-review/scripts/pr-sonar.sh +0 -93
  63. agentirc_cli-9.6.1/.claude/skills/pr-review/scripts/workflow.sh +0 -106
  64. agentirc_cli-9.6.1/agentirc/_internal/bots/bot_manager.py +0 -38
  65. agentirc_cli-9.6.1/agentirc/_internal/bots/http_listener.py +0 -36
  66. agentirc_cli-9.6.1/uv.lock +0 -676
  67. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/.github/workflows/publish.yml +0 -0
  68. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/LICENSE +0 -0
  69. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/__init__.py +0 -0
  70. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/__main__.py +0 -0
  71. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/_internal/__init__.py +0 -0
  72. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/_internal/aio.py +0 -0
  73. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/_internal/bots/__init__.py +0 -0
  74. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/_internal/cli_shared/__init__.py +0 -0
  75. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/_internal/cli_shared/constants.py +0 -0
  76. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/_internal/cli_shared/mesh.py +0 -0
  77. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/_internal/constants.py +0 -0
  78. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/_internal/event_subscriptions.py +0 -0
  79. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/_internal/pidfile.py +0 -0
  80. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/_internal/protocol/__init__.py +0 -0
  81. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/_internal/protocol/message.py +0 -0
  82. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/_internal/protocol/replies.py +0 -0
  83. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/_internal/telemetry/__init__.py +0 -0
  84. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/_internal/telemetry/audit.py +0 -0
  85. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/_internal/telemetry/context.py +0 -0
  86. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/_internal/telemetry/metrics.py +0 -0
  87. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/_internal/telemetry/tracing.py +0 -0
  88. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/_internal/virtual_client.py +0 -0
  89. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/channel.py +0 -0
  90. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/client.py +0 -0
  91. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/config.py +0 -0
  92. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/events.py +0 -0
  93. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/history_store.py +0 -0
  94. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/protocol.py +0 -0
  95. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/remote_client.py +0 -0
  96. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/room_store.py +0 -0
  97. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/rooms_util.py +0 -0
  98. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/server_link.py +0 -0
  99. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/skill.py +0 -0
  100. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/skills/__init__.py +0 -0
  101. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/skills/history.py +0 -0
  102. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/skills/icon.py +0 -0
  103. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/skills/rooms.py +0 -0
  104. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/skills/threads.py +0 -0
  105. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/thread_store.py +0 -0
  106. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/agentirc/virtual_client.py +0 -0
  107. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/docs/cli.md +0 -0
  108. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/docs/deployment.md +0 -0
  109. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/docs/extension-api.md +0 -0
  110. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/docs/superpowers/specs/2026-04-30-bootstrap-design.md +0 -0
  111. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/docs/superpowers/specs/2026-05-01-bot-extension-api-design.md +0 -0
  112. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/docs/superpowers/specs/2026-05-01-task14-audit.md +0 -0
  113. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/__init__.py +0 -0
  114. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/_helpers.py +0 -0
  115. {agentirc_cli-9.6.1/tests/telemetry → agentirc_cli-9.7.0/tests/bots}/__init__.py +0 -0
  116. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/telemetry/_fakes.py +0 -0
  117. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/telemetry/_metrics_helpers.py +0 -0
  118. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/telemetry/test_audit_emit.py +0 -0
  119. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/telemetry/test_audit_lifecycle.py +0 -0
  120. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/telemetry/test_audit_module.py +0 -0
  121. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/telemetry/test_audit_parse_error.py +0 -0
  122. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/telemetry/test_config.py +0 -0
  123. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/telemetry/test_dispatch_span.py +0 -0
  124. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/telemetry/test_emit_event_span.py +0 -0
  125. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/telemetry/test_metrics_init.py +0 -0
  126. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/telemetry/test_metrics_s2s.py +0 -0
  127. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/telemetry/test_outbound_inject.py +0 -0
  128. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/telemetry/test_parse_error.py +0 -0
  129. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/telemetry/test_s2s_relay_span.py +0 -0
  130. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/telemetry/test_server_init.py +0 -0
  131. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/telemetry/test_server_link_inject.py +0 -0
  132. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/telemetry/test_tracing.py +0 -0
  133. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/test_api_stability_embedding.py +0 -0
  134. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/test_bot_capability.py +0 -0
  135. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/test_channel.py +0 -0
  136. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/test_cli.py +0 -0
  137. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/test_config_loader.py +0 -0
  138. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/test_connection.py +0 -0
  139. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/test_discovery.py +0 -0
  140. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/test_event_subscriptions.py +0 -0
  141. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/test_eventpub.py +0 -0
  142. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/test_events_basic.py +0 -0
  143. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/test_events_catalog.py +0 -0
  144. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/test_events_federation.py +0 -0
  145. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/test_events_history.py +0 -0
  146. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/test_events_lifecycle.py +0 -0
  147. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/test_events_reserved_nick.py +0 -0
  148. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/test_federation.py +0 -0
  149. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/test_history.py +0 -0
  150. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/test_link_reconnect.py +0 -0
  151. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/test_mentions.py +0 -0
  152. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/test_messaging.py +0 -0
  153. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/test_modes.py +0 -0
  154. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/test_protocol_bot_exports.py +0 -0
  155. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/test_room_persistence.py +0 -0
  156. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/test_rooms_federation.py +0 -0
  157. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/test_rooms_integration.py +0 -0
  158. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/test_server_icon_skill.py +0 -0
  159. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/test_skills.py +0 -0
  160. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/test_threads.py +0 -0
  161. {agentirc_cli-9.6.1 → agentirc_cli-9.7.0}/tests/test_wire_format_envelope.py +0 -0
@@ -0,0 +1,243 @@
1
+ ---
2
+ name: assign-to-workforce
3
+ description: >
4
+ Fan out a converged devague plan's dependency waves to parallel agents in
5
+ isolated git worktrees, one agent per task per wave, with TDD-gated merges
6
+ by the main agent. Human gates: the exported spec, the implementation split
7
+ plan (task map + per-task agent/model proposal + go/no-go), and the final PR.
8
+ The devague CLI stays deterministic and non-orchestrating (#20) — it only
9
+ *describes* the graph via `devague plan waves`; the operator (main agent)
10
+ performs the fan-out. Use when the user says "assign to workforce",
11
+ "fan out the plan", "parallel subagents", or after /spec-to-plan exports a
12
+ plan. Authored and maintained in agentculture/devague (origin = devague);
13
+ guildmaster pulls this skill from here and broadcasts it to the AgentCulture
14
+ mesh — it is NOT vendored from guildmaster like the other skills here.
15
+ type: command
16
+ ---
17
+
18
+ # assign-to-workforce — fan out a converged plan's waves to parallel agents
19
+
20
+ The skill is named **`assign-to-workforce`**; the product/CLI it reads is the
21
+ **`devague plan waves`** command. (The prior leg — turning a spec into a plan —
22
+ is the sibling **`/spec-to-plan`** skill.)
23
+
24
+ `assign-to-workforce` takes a **converged devague plan** and fans out its
25
+ dependency waves to parallel agents (subagents, teammate agents, or generalist
26
+ agents) — one agent per task per wave — each working in an **isolated git
27
+ worktree**. The main agent merges each completed worktree gated by TDD. The
28
+ human owns exactly three gates: the exported spec, the implementation split
29
+ plan, and the final PR.
30
+
31
+ The devague CLI is **never orchestrated by devague itself** — `devague plan
32
+ waves` describes the dependency graph (#20); it does not spawn agents, manage
33
+ worktrees, mark tasks done, or pick a backend. The fan-out is the *operator's*
34
+ job — this skill and the main agent perform it.
35
+
36
+ ## How to run
37
+
38
+ The entry point is `scripts/assign-to-workforce.sh`. Invoke it from the
39
+ repository whose plan you are implementing (plans persist under `.devague/`
40
+ in the current directory):
41
+
42
+ ```bash
43
+ bash .claude/skills/assign-to-workforce/scripts/assign-to-workforce.sh split-plan [--plan <slug>]
44
+ bash .claude/skills/assign-to-workforce/scripts/assign-to-workforce.sh waves [--plan <slug>] [--json]
45
+ bash .claude/skills/assign-to-workforce/scripts/assign-to-workforce.sh help
46
+ ```
47
+
48
+ It resolves the CLI portably — an installed `devague` on `PATH` (the normal
49
+ case), falling back to `uv run devague` when you are inside the devague
50
+ checkout, else an install hint. The `split-plan` subcommand reads
51
+ `devague plan waves --json` and renders the human-facing implementation split
52
+ plan: task map, proposed per-task agent + model assignment, and the go/no-go
53
+ question. The `waves` subcommand forwards to `devague plan waves` verbatim.
54
+
55
+ ### Usage
56
+
57
+ | Subcommand | What it does |
58
+ |------------|--------------|
59
+ | `split-plan [--plan S]` | Read `devague plan waves` and print the implementation split plan — task map with per-task agent + model proposal — ready for human go/no-go review. |
60
+ | `waves [--plan S] [--json]` | Forward to `devague plan waves [--json]`. Read-only; lists wave batches. On a converged plan exits 0 listing the waves. |
61
+ | `help` | Print usage. |
62
+
63
+ ## The full flow
64
+
65
+ The flow has three human gates and one automated TDD merge loop.
66
+
67
+ ### Human gate 1 — the exported spec
68
+
69
+ The plan is seeded from a converged frame (`devague plan new --frame <slug>`).
70
+ The human reviewed and approved the spec when it was exported by the `/think`
71
+ skill. No re-approval needed here — the spec gate is already closed.
72
+
73
+ ### Human gate 2 — the implementation split plan
74
+
75
+ Before any task is assigned, the main agent presents the **implementation split
76
+ plan** for human go/no-go. This is the only gate the human owns at the
77
+ implementation stage (per task, the TDD gate is the main agent's).
78
+
79
+ The split plan contains:
80
+
81
+ 1. **Task map** — every task id, its one-line summary, acceptance criteria, and
82
+ the wave it belongs to (from `devague plan waves`).
83
+ 2. **Per-task agent + model proposal** — for each task: the proposed agent type
84
+ (subagent / teammate / generalist), the proposed model (e.g. a cheaper/faster
85
+ model for a well-scoped task), and the scope justification (why this task is
86
+ safe to delegate).
87
+ 3. **Go/no-go question** — explicit human decision: "Approve this split and
88
+ assign the plan to the workforce, or edit it first?"
89
+
90
+ The human may edit any row (agent type, model, scope) before approving. The
91
+ plan is model-agnostic — devague does not pick a backend (#20).
92
+
93
+ Run `split-plan` to print the proposed table:
94
+
95
+ ```bash
96
+ bash .claude/skills/assign-to-workforce/scripts/assign-to-workforce.sh split-plan
97
+ ```
98
+
99
+ Do not proceed to fan-out until the human approves the split plan.
100
+
101
+ ### Fan-out — one agent per task per wave in isolated worktrees
102
+
103
+ Once the human approves, the main agent fans out each wave in order:
104
+
105
+ 1. **Create an isolated git worktree** for each task in the current wave:
106
+
107
+ ```bash
108
+ git worktree add ../worktrees/agent-<task-id> -b agent/<task-id>
109
+ ```
110
+
111
+ 2. **Spawn a task agent** inside that worktree (using the approved model from
112
+ the split plan), with:
113
+ - The task id, summary, and acceptance criteria as its brief.
114
+ - Instruction to work **test-first** (TDD): write the failing test(s) that
115
+ match the acceptance criteria before implementing.
116
+ - Instruction to commit its work to the worktree branch.
117
+
118
+ 3. **Same-wave tasks run in parallel** (within-wave tasks have no
119
+ inter-task dependency; the dependency graph guarantees this). Same-file
120
+ overlap surfaces as a merge conflict at reconcile time, not a live race —
121
+ isolated worktrees prevent clobbering.
122
+
123
+ 4. **Wait for all tasks in the wave to complete** before starting the next wave.
124
+
125
+ ### TDD-gated merge — main agent, no human per task
126
+
127
+ For each completed task worktree, the main agent:
128
+
129
+ 1. **Runs the task's tests before merge** (on the main branch): baseline must
130
+ pass (or the relevant tests must be absent — the task adds them).
131
+ 2. **Merges the worktree branch** into the main branch:
132
+
133
+ ```bash
134
+ git merge --no-ff agent/<task-id>
135
+ ```
136
+
137
+ 3. **Runs the task's tests after merge**: they must pass. If they do not, the
138
+ merge is reverted and the task agent is given the failure output to fix.
139
+ 4. **Removes the worktree** once the merge is accepted:
140
+
141
+ ```bash
142
+ git worktree remove ../worktrees/agent-<task-id>
143
+ ```
144
+
145
+ The human does **not** review individual task merges. Per-task acceptance is
146
+ the main agent's responsibility — the TDD gate (tests pass before AND after
147
+ merge) plus the task's acceptance criteria. This mirrors the non-authoritative
148
+ working state pattern of the Human Review Loop (#17): per-task merge records
149
+ are uncommitted working state; the authoritative human gate is the final PR.
150
+
151
+ Advance to the next wave only after all tasks in the current wave are merged
152
+ and their tests pass.
153
+
154
+ ### Human gate 3 — the final PR
155
+
156
+ Once all waves are merged and the full test suite passes, the main agent opens
157
+ a PR via the repo's PR workflow (e.g. the `cicd` skill's `agex pr open`, the
158
+ `pr-review` skill, or `gh pr create`). The human reviews and merges. This
159
+ is the last and only remaining human gate.
160
+
161
+ ## Hard rules (do not violate)
162
+
163
+ These protect the human-gate contract and the TDD guarantee.
164
+
165
+ - **Present the split plan before any fan-out.** Never spawn a task agent
166
+ without prior human approval of the implementation split plan (gate 2). The
167
+ split plan is the human's only implementation-stage decision.
168
+ - **One worktree per task.** Never run two tasks in the same worktree — file
169
+ contention is managed by isolation, not by trust in the dependency graph.
170
+ The dependency graph guarantees *logical* independence within a wave, not
171
+ *file* disjointness. Conflicts surface at merge time.
172
+ - **Tests before AND after merge — no exceptions.** The TDD gate must pass on
173
+ both sides. A merge that makes tests pass only after (not before) means the
174
+ baseline was already broken — fix the baseline first.
175
+ - **Human does not gate per-task merges.** The TDD contract replaces the
176
+ human here. Do not pause for human approval between wave tasks.
177
+ - **devague CLI is not orchestrated.** `devague plan waves` is read-only
178
+ scheduling metadata (#20). Never run `devague plan` commands inside a task
179
+ worktree to "mark a task done" or modify plan state from a subagent.
180
+ - **Three gates only.** The human's gates are: (1) the exported spec, (2) the
181
+ implementation split plan, (3) the final PR. No silent fourth gate.
182
+ - **No LLM calls in the devague CLI.** The CLI is deterministic. This skill
183
+ adds orchestration convention, not CLI behavior.
184
+
185
+ ## Output contract
186
+
187
+ The `split-plan` subcommand prints to **stdout** and exits 0 when a converged
188
+ plan is found. On error (no plan, cyclic graph) it exits non-zero with a
189
+ `hint:` line on stderr. The `waves` subcommand forwards the CLI's own output
190
+ contract (stdout, `--json` for structured output, exit 0 on success).
191
+
192
+ ## Worked example
193
+
194
+ Picking up after `/spec-to-plan` exported a plan for the frame `my-feature`:
195
+
196
+ ```bash
197
+ a() { bash .claude/skills/assign-to-workforce/scripts/assign-to-workforce.sh "$@"; }
198
+
199
+ # 1. Inspect the waves
200
+ a waves
201
+
202
+ # 2. Present the implementation split plan for human review
203
+ a split-plan
204
+
205
+ # --- HUMAN: review the table, edit agent/model assignments if needed,
206
+ # then say "approved" to proceed ---
207
+
208
+ # 3. Fan out wave 1 (t1, t2, t3 are independent — run in parallel)
209
+ git worktree add ../worktrees/agent-t1 -b agent/t1
210
+ git worktree add ../worktrees/agent-t2 -b agent/t2
211
+ git worktree add ../worktrees/agent-t3 -b agent/t3
212
+ # ... spawn task agents in each worktree, await completion ...
213
+
214
+ # 4. TDD-gated merge for each wave-1 task (no human per task)
215
+ git merge --no-ff agent/t1 # tests pass before + after
216
+ git worktree remove ../worktrees/agent-t1
217
+ git merge --no-ff agent/t2
218
+ git worktree remove ../worktrees/agent-t2
219
+ git merge --no-ff agent/t3
220
+ git worktree remove ../worktrees/agent-t3
221
+
222
+ # 5. Advance to wave 2 (t4 depends on t1–t3 being merged)
223
+ git worktree add ../worktrees/agent-t4 -b agent/t4
224
+ # ... spawn, await, merge with TDD gate, remove worktree ...
225
+
226
+ # 6. Open the final PR (human gate 3) via your repo's PR workflow —
227
+ # e.g. the cicd skill (`agex pr open`), the pr-review skill, or `gh pr create`.
228
+ ```
229
+
230
+ The exported plan-md from `devague plan export` is the standing brief for
231
+ each task agent — its task id, summary, acceptance criteria, and the targets
232
+ it covers are already in that file.
233
+
234
+ ## Provenance
235
+
236
+ This is a **first-party** skill — its origin is `agentculture/devague`, where
237
+ the devague agent maintains it alongside the tools it operates (dogfooding),
238
+ next to its siblings `/think` and `/spec-to-plan`. It is the *third* skill in
239
+ that outbound family, covering the implementation leg after a plan converges.
240
+ The flow runs the *opposite* direction of the vendored guildmaster skills:
241
+ guildmaster pulls this **from** devague and broadcasts it to the rest of the
242
+ AgentCulture mesh. The `cite, don't import` policy still holds: downstream repos copy it,
243
+ they don't symlink or depend on it. See `docs/skill-sources.md`.
@@ -0,0 +1,213 @@
1
+ #!/usr/bin/env bash
2
+ # assign-to-workforce.sh — fan out devague plan waves to parallel agents.
3
+ #
4
+ # The skill is named `assign-to-workforce`; it reads `devague plan waves`
5
+ # (scheduling metadata produced by the /spec-to-plan skill) and renders the
6
+ # implementation split plan: task map + per-task agent/model proposal + a
7
+ # go/no-go prompt for the human. The actual fan-out (worktree creation,
8
+ # spawning, TDD-gated merges) is performed by the operator/main agent once
9
+ # the human approves the split plan.
10
+ #
11
+ # The devague CLI is non-orchestrating (#20): `devague plan waves` describes
12
+ # the dependency graph; it does not spawn agents, manage worktrees, or pick
13
+ # a backend. This wrapper is the operator-facing helper.
14
+ #
15
+ # Origin: authored and maintained in agentculture/devague. guildmaster pulls this
16
+ # skill from here and broadcasts it to the rest of the AgentCulture mesh, so
17
+ # it is written to run anywhere — portable bash, no devague-checkout assumptions.
18
+ #
19
+ # Plans persist under .devague/ in the current directory, so run from the repo
20
+ # you are implementing.
21
+
22
+ set -euo pipefail
23
+
24
+ # ── resolve the devague CLI (mesh-first, then local-dev fallback) ───────────
25
+ DEVAGUE=()
26
+ resolve_devague() {
27
+ if command -v devague >/dev/null 2>&1; then
28
+ DEVAGUE=(devague) # installed tool — the normal mesh case
29
+ return 0
30
+ fi
31
+ # Local-dev fallback: inside the devague checkout, run via uv.
32
+ local dir="$PWD"
33
+ while [ -n "$dir" ] && [ "$dir" != "/" ]; do
34
+ if [ -f "$dir/pyproject.toml" ] \
35
+ && grep -q '^name = "devague"' "$dir/pyproject.toml" 2>/dev/null; then
36
+ if command -v uv >/dev/null 2>&1; then
37
+ DEVAGUE=(uv run devague)
38
+ return 0
39
+ fi
40
+ break
41
+ fi
42
+ dir=$(dirname "$dir")
43
+ done
44
+ cat >&2 <<'EOF'
45
+ error: devague CLI not found.
46
+ hint: install it with `uv tool install devague` (or `pipx install devague`),
47
+ or run from inside the devague checkout with `uv` available.
48
+ https://github.com/agentculture/devague
49
+ EOF
50
+ return 1
51
+ }
52
+
53
+ usage() {
54
+ cat <<'EOF'
55
+ assign-to-workforce.sh — fan out devague plan waves to parallel agents.
56
+
57
+ Usage:
58
+ assign-to-workforce.sh split-plan [--plan <slug>] print the implementation split plan
59
+ assign-to-workforce.sh waves [--plan <slug>] [--json] list dependency waves
60
+ assign-to-workforce.sh help this help
61
+
62
+ Commands:
63
+ split-plan Read `devague plan waves --json` and render the human-facing
64
+ implementation split plan: task map + per-task agent/model
65
+ proposal + go/no-go. Present this to the human before any
66
+ fan-out; do not proceed without approval.
67
+ waves Forward `devague plan waves` (and any extra flags) verbatim.
68
+ On a converged plan exits 0 and lists the dependency waves.
69
+
70
+ Plans persist under .devague/ in the current directory — run from the repo
71
+ you are implementing. Results go to stdout, diagnostics to stderr.
72
+
73
+ Human gates (three only):
74
+ 1. The exported spec (already closed by the /think leg).
75
+ 2. This implementation split plan (go/no-go to assign to workforce).
76
+ 3. The final PR (opened by the main agent via the repo's PR workflow,
77
+ e.g. `cicd` / `agex pr open`, `pr-review`, or `gh pr create`).
78
+
79
+ The devague CLI is non-orchestrating (#20): `devague plan waves` describes
80
+ the graph; the operator performs the fan-out. One worktree per task; TDD
81
+ gates every merge (tests pass before AND after merge); no human per task.
82
+ EOF
83
+ }
84
+
85
+ # ── split-plan: render the implementation split plan for human review ────────
86
+ cmd_split_plan() {
87
+ local extra_args=()
88
+ # Forward any --plan flag so waves targets the right plan.
89
+ while [ $# -gt 0 ]; do
90
+ extra_args+=("$1")
91
+ shift
92
+ done
93
+
94
+ local waves_json tmp_err waves_rc old_exit_trap
95
+ # Clean up the temp file on any exit path — including a signal after its
96
+ # creation — WITHOUT permanently changing the script's process-global EXIT
97
+ # handling. Capture any prior EXIT trap BEFORE mktemp (that capture forks a
98
+ # subshell, so doing it first keeps it out of the untracked-file window),
99
+ # then install our cleanup trap on the line immediately after mktemp, and
100
+ # restore the prior trap once the file is safely gone (#30; PR #31 review;
101
+ # devague#32).
102
+ old_exit_trap="$(trap -p EXIT)"
103
+ tmp_err="$(mktemp)"
104
+ trap 'rm -f "$tmp_err"' EXIT
105
+ set +e
106
+ waves_json="$("${DEVAGUE[@]}" plan waves --json "${extra_args[@]}" 2>"$tmp_err")"
107
+ waves_rc=$?
108
+ set -e
109
+ local waves_err
110
+ waves_err="$(cat "$tmp_err")"
111
+ rm -f "$tmp_err"
112
+ trap - EXIT
113
+ eval "${old_exit_trap}" # empty string is a no-op; re-installs a prior trap if any
114
+
115
+ if [ "$waves_rc" -ne 0 ]; then
116
+ printf '%s\n' "$waves_err" >&2
117
+ return "$waves_rc"
118
+ fi
119
+
120
+ DEVAGUE_WAVES_JSON="$waves_json" python3 - <<'PY'
121
+ import json
122
+ import os
123
+ import sys
124
+
125
+ raw = os.environ.get("DEVAGUE_WAVES_JSON", "").strip()
126
+ if not raw:
127
+ print("error: no waves output from devague plan waves", file=sys.stderr)
128
+ print("hint: ensure a converged plan exists (devague plan converge)", file=sys.stderr)
129
+ sys.exit(1)
130
+
131
+ try:
132
+ data = json.loads(raw)
133
+ except json.JSONDecodeError as exc:
134
+ print(f"error: could not parse waves JSON: {exc}", file=sys.stderr)
135
+ sys.exit(1)
136
+
137
+ plan_slug = data.get("plan", "(unknown)")
138
+ waves = data.get("waves") or []
139
+
140
+ print(f"Implementation split plan — plan: {plan_slug}")
141
+ print()
142
+ print("Dependency waves (from `devague plan waves`):")
143
+ for i, wave in enumerate(waves, 1):
144
+ tasks = ", ".join(wave)
145
+ print(f" Wave {i}: [{tasks}]")
146
+
147
+ print()
148
+ print("Task assignments (proposed — edit before approving):")
149
+ print()
150
+
151
+ headers = ("Task", "Wave", "Summary", "Agent type", "Model", "Scope note")
152
+ rows = []
153
+ for i, wave in enumerate(waves, 1):
154
+ for task_id in wave:
155
+ rows.append((
156
+ task_id,
157
+ str(i),
158
+ "(see plan export for summary + acceptance criteria)",
159
+ "subagent",
160
+ "cheaper/faster",
161
+ "TDD-scoped task; isolated worktree; tests gate merge",
162
+ ))
163
+
164
+ col_widths = [max(len(h), max((len(r[j]) for r in rows), default=0))
165
+ for j, h in enumerate(headers)]
166
+
167
+ def row_str(cells):
168
+ return "| " + " | ".join(c.ljust(w) for c, w in zip(cells, col_widths)) + " |"
169
+
170
+ sep = "| " + " | ".join("-" * w for w in col_widths) + " |"
171
+ print(row_str(headers))
172
+ print(sep)
173
+ for row in rows:
174
+ print(row_str(row))
175
+
176
+ print()
177
+ print("Go/no-go: review the table above, edit agent type / model / scope as needed,")
178
+ print("then confirm: \"Approved — assign to workforce\" or \"Edit first\".")
179
+ print()
180
+ print("Once approved, fan out wave by wave:")
181
+ print(" 1. Create one git worktree per task in the wave.")
182
+ print(" 2. Spawn a task agent per worktree (brief = task summary + acceptance criteria).")
183
+ print(" 3. Await all tasks in the wave; then TDD-gate each merge (tests before + after).")
184
+ print(" 4. Advance to the next wave.")
185
+ print(" 5. Open the final PR (human gate 3) after all waves merge and tests pass.")
186
+ PY
187
+ }
188
+
189
+ main() {
190
+ case "${1:-help}" in
191
+ help | -h | --help)
192
+ usage
193
+ return 0
194
+ ;;
195
+ split-plan)
196
+ shift
197
+ resolve_devague
198
+ cmd_split_plan "$@"
199
+ ;;
200
+ waves)
201
+ shift
202
+ resolve_devague
203
+ exec "${DEVAGUE[@]}" plan waves "$@"
204
+ ;;
205
+ *)
206
+ printf 'error: unknown subcommand: %s\n' "$1" >&2
207
+ printf 'hint: run `assign-to-workforce.sh help` for usage\n' >&2
208
+ return 1
209
+ ;;
210
+ esac
211
+ }
212
+
213
+ main "$@"
@@ -0,0 +1,196 @@
1
+ ---
2
+ name: cicd
3
+ description: >
4
+ agentirc's CI/CD lane, layered on `agex pr`. Delegates lint / open /
5
+ read / reply / delta to agex; adds two extensions — `status`
6
+ (SonarCloud quality gate + hotspots + unresolved-thread tally) and
7
+ `await` (read --wait + status with non-zero exit on Sonar ERROR or
8
+ unresolved threads). Use when: creating PRs in agentirc, handling
9
+ review feedback, polling CI status, or the user says "create PR",
10
+ "review comments", "address feedback", "resolve threads". Renamed
11
+ from `pr-review` in steward 0.7.0; rebased on agex in 0.12.0.
12
+ ---
13
+
14
+ # CI/CD — agentirc edition
15
+
16
+ `agex pr` (in `agentculture/agex-cli`) is the upstream for the
17
+ five core PR-lifecycle verbs — `lint`, `open`, `read`, `reply`,
18
+ `delta`. The upstream (steward) used to vendor parallel scripts for each;
19
+ in 0.12.0 those vendored copies were dropped in favor of delegating to
20
+ `agex`. What's left in this skill is **the gating layer on top of agex**:
21
+
22
+ - `status` — SonarCloud quality gate, OPEN issues, hotspots, deploy
23
+ preview URL, unresolved-inline-thread tally.
24
+ - `await` — composes `agex pr read --wait` with `status` and gates on
25
+ Sonar `ERROR` / unresolved threads. The single command to run after
26
+ pushing a fix when you want "wake me when this PR is triage-able."
27
+
28
+ Those two are the unique surface today. The `await` combo verb
29
+ landed natively in agex
30
+ ([agex-cli#41](https://github.com/agentculture/agex-cli/issues/41), now
31
+ closed); the gate extras that aren't yet native — SonarCloud hotspots,
32
+ deploy-preview URL, an explicit resolved/unresolved thread tally — are
33
+ tracked upstream in
34
+ [agex-cli#52](https://github.com/agentculture/agex-cli/issues/52) and
35
+ migrate out of this skill once they land.
36
+
37
+ The workflow is encapsulated in `scripts/workflow.sh` — follow that
38
+ (or call `agex pr` directly).
39
+
40
+ > **Vendored from `../steward/.claude/skills/cicd/` per
41
+ > `docs/steward/onboarding.md`.** Re-sync explicitly when steward updates
42
+ > upstream — there is no auto-sync.
43
+
44
+ ## Prerequisites
45
+
46
+ Hard requirements: `agex` (>=0.1), `gh` (GitHub CLI), `jq`, `bash`,
47
+ `python3` (stdlib only), `curl` (used by `pr-status.sh`).
48
+
49
+ Install agex once:
50
+
51
+ ```bash
52
+ uv tool install agex-cli # or: pip install --user agex-cli
53
+ ```
54
+
55
+ Soft requirement: `PyYAML` is needed **only for suffix mode** of the
56
+ sibling `agent-config` skill, where it parses Culture's server
57
+ manifest. Every `cicd` script works without it; suffix mode prints a
58
+ clear install hint when invoked without it.
59
+
60
+ Per-machine paths (sibling-project layout) live in
61
+ `.claude/skills.local.yaml`; see the committed `.example` for the
62
+ schema. `agex pr delta` reads the same file.
63
+
64
+ ## How to run
65
+
66
+ `scripts/workflow.sh` is the entry point. Subcommands:
67
+
68
+ | Command | What it does |
69
+ |---------|--------------|
70
+ | `workflow.sh lint` | `agex pr lint --exit-on-violation` — portability + alignment-trigger check. |
71
+ | `workflow.sh open [gh-flags]` | `agex pr open --delayed-read`. Creates the PR, then polls 180s for an initial briefing. `--title TITLE` required; body via `--body-file PATH` or stdin. |
72
+ | `workflow.sh read [PR] [--wait N]` | `agex pr read`. One-shot briefing (CI checks, SonarCloud gate + new issues, all comments, next-step footer). Pass `--wait N` to poll up to N seconds for required reviewers. |
73
+ | `workflow.sh reply <PR>` | `agex pr reply <PR>` — batch JSONL replies (stdin) + thread resolve. agex auto-signs from `culture.yaml`. |
74
+ | `workflow.sh delta` | `agex pr delta` — sibling alignment dump. |
75
+ | `workflow.sh status <PR>` | **agentirc extension.** `pr-status.sh` — Sonar gate, OPEN issues, hotspots, unresolved-thread breakdown, deploy preview URL. Authoritative gate for `await`. |
76
+ | `workflow.sh await <PR>` | **agentirc extension.** `agex pr read --wait` then `status`. Exits non-zero on Sonar ERROR or unresolved threads. Tunables: `STEWARD_PR_AWAIT_WAIT` (default 1800s passed to `--wait`), `STEWARD_PR_AWAIT_SECONDS` (legacy fixed pre-sleep, deprecated). |
77
+ | `workflow.sh help` | Print the list. |
78
+
79
+ You can also call `agex pr <verb>` directly — `workflow.sh` is a
80
+ typing-saver around the same verbs. The agentirc `status` and `await`
81
+ extensions only have shell entry points.
82
+
83
+ The vendored single-comment helper `pr-reply.sh` (plus its
84
+ `_resolve-nick.sh` dependency) is still shipped — useful for one-off
85
+ single-comment replies that don't merit a full batch JSONL run. It is not
86
+ called by `workflow.sh` anymore. The vendored `portability-lint.sh`
87
+ is also still shipped — agentirc's CI lint job (`.github/workflows/tests.yml`)
88
+ runs it directly. `portability-lint.sh` catches two recurring bug classes
89
+ for agentirc PRs (which touch the bootstrap spec, `CLAUDE.md`, vendored
90
+ skills, and the IRCd server core):
91
+
92
+ - **Path leaks** — committing absolute home-directory paths that work only
93
+ on the author's machine, breaking CI and other contributors.
94
+ - **Per-user config dependencies** — referencing dotfiles under the user's
95
+ home dir in repo guidance, breaking reproducibility.
96
+
97
+ Both helpers are scheduled for follow-up migration to agex.
98
+
99
+ ## Long waits (background polling)
100
+
101
+ `agex pr read --wait N` polls in-session for up to N seconds. The
102
+ Anthropic prompt cache has a 5-minute TTL; sleeping past it burns
103
+ context every cache miss. Two ways to drive the wait:
104
+
105
+ - **Synchronous** — `workflow.sh await <PR>` after `gh pr create` /
106
+ `workflow.sh open`. Fine when readiness is expected within ~5
107
+ minutes.
108
+ - **Asynchronous** — for longer waits, run `agex pr read --wait NNN`
109
+ inside a background subagent (Agent tool, `run_in_background: true`)
110
+ so the main session only pays the cache cost when readiness fires.
111
+ The subagent's only job is to invoke `agex pr read --wait` and echo
112
+ its headline back. The parent triages with `workflow.sh await`
113
+ when the notification arrives. The user can interrupt with
114
+ TaskStop.
115
+
116
+ This pattern was originally borrowed from sibling repo
117
+ [`agentculture/cfafi`](https://github.com/agentculture/cfafi)'s `poll`
118
+ skill. The async guidance is also filed upstream
119
+ ([agex-cli#41](https://github.com/agentculture/agex-cli/issues/41)).
120
+
121
+ ## Conventions
122
+
123
+ `agex pr` emits a **"Next step:"** footer at the end of every command
124
+ that names the right next verb (the same chain `agex learn cicd`
125
+ documents) — follow that rather than memorizing an order. `workflow.sh
126
+ help` mirrors the verb table when you need the agentirc-layer
127
+ extensions (`status`, `await`) on top.
128
+
129
+ Branch naming: `fix/<desc>`, `feat/<desc>`, `docs/<desc>`,
130
+ `skill/<name>`. PR / comment signature: `- <nick> (Claude)`, where
131
+ `<nick>` is resolved by `agex` from the agent's own `culture.yaml`
132
+ (first agent's `suffix`), falling back to the git-repo basename. For
133
+ agentirc (no `culture.yaml` present), `_resolve-nick.sh` falls back to
134
+ the repo basename — `agentirc`. agex auto-appends the signature on
135
+ `pr open` and `pr reply` only when the body isn't already signed.
136
+
137
+ ## Finishing a branch
138
+
139
+ When implementation on a branch is complete and tests pass, go straight
140
+ to `workflow.sh open` (push the branch + open the PR). Do **not** stop to
141
+ present a *merge / PR / keep / discard* menu and wait for a choice — in
142
+ AgentCulture the standing default is **always "push and create a Pull
143
+ Request."** This overrides the Superpowers `finishing-a-development-branch`
144
+ skill's interactive menu, which otherwise pauses the flow at the moment
145
+ work is ready to integrate. Merge-locally, keep-as-is, and discard happen
146
+ only when the user explicitly asks for one of them.
147
+
148
+ ## Triage rules
149
+
150
+ For every comment, decide **FIX** or **PUSHBACK** with reasoning.
151
+
152
+ Default to **FIX** for: portability complaints (always valid for
153
+ agentirc — recurring bug class for PRs touching the bootstrap spec,
154
+ `CLAUDE.md`, vendored skills, or the IRCd server core), test or doc
155
+ requests, style nits aligned with workspace conventions.
156
+
157
+ Default to **PUSHBACK** for: architecture opinions that conflict with
158
+ the workspace or repo `CLAUDE.md` invariants; note that the all-backends
159
+ rule does NOT apply inside agentirc (agentirc has no backends — that rule
160
+ lives in culture); greenfield false-positives (e.g. "add tests" before
161
+ there's any source — defer to a later PR, don't refuse).
162
+
163
+ ### Alignment-delta rule
164
+
165
+ If the PR touches `CLAUDE.md`, `culture.yaml`, or anything under
166
+ `.claude/skills/`, run `workflow.sh delta` **before** declaring FIX or
167
+ PUSHBACK on each comment. Note any sibling that needs a follow-up PR
168
+ and mention it in your reply.
169
+
170
+ ## Greenfield-aware steps
171
+
172
+ The lint and the workflow script are always-on. Stack-specific steps
173
+ are conditional and currently no-op (greenfield repo):
174
+
175
+ ```bash
176
+ [ -d tests ] && [ -f pyproject.toml ] && uv run pytest tests/ -x -q
177
+ [ -f pyproject.toml ] && bump_version_per_project_convention # see project README
178
+ [ -f .markdownlint-cli2.yaml ] && markdownlint-cli2 "$(git diff --name-only --cached '*.md')"
179
+ ```
180
+
181
+ Revisit each line as the corresponding stack element actually lands.
182
+ A `pr lint --extra=tests,version,markdown` ask is filed upstream
183
+ ([agex-cli#41](https://github.com/agentculture/agex-cli/issues/41)).
184
+
185
+ ## Reply etiquette
186
+
187
+ Every comment must get a reply — no silent fixes. `agex pr reply`
188
+ includes thread-resolve by default. Reference the review-comment IDs
189
+ in the fix-up commit message.
190
+
191
+ The `status` extension queries SonarCloud directly (it predates the
192
+ upstream Sonar integration in `agex pr read`). Both surfaces are
193
+ trustworthy — `agex pr read` for display in the briefing, `status` for
194
+ the gate. agentirc isn't yet a registered mesh agent, so the
195
+ post-merge IRC ping that Culture's `pr-review` includes is still
196
+ skipped — that returns when agentirc joins the mesh.