@chorus-aidlc/chorus-openclaw-plugin 0.4.0 → 0.5.3

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 (58) hide show
  1. package/README.md +208 -278
  2. package/dist/commands.d.ts +5 -0
  3. package/dist/commands.d.ts.map +1 -0
  4. package/dist/commands.js +147 -0
  5. package/dist/commands.js.map +1 -0
  6. package/dist/config.d.ts +38 -0
  7. package/dist/config.d.ts.map +1 -0
  8. package/dist/config.js +57 -0
  9. package/dist/config.js.map +1 -0
  10. package/dist/event-router.d.ts +55 -0
  11. package/dist/event-router.d.ts.map +1 -0
  12. package/dist/event-router.js +157 -0
  13. package/dist/event-router.js.map +1 -0
  14. package/dist/index.d.ts +3 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +108 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/mcp-client.d.ts +37 -0
  19. package/dist/mcp-client.d.ts.map +1 -0
  20. package/dist/mcp-client.js +137 -0
  21. package/dist/mcp-client.js.map +1 -0
  22. package/dist/mcp-registration.d.ts +25 -0
  23. package/dist/mcp-registration.d.ts.map +1 -0
  24. package/dist/mcp-registration.js +93 -0
  25. package/dist/mcp-registration.js.map +1 -0
  26. package/dist/sse-listener.d.ts +37 -0
  27. package/dist/sse-listener.d.ts.map +1 -0
  28. package/dist/sse-listener.js +152 -0
  29. package/dist/sse-listener.js.map +1 -0
  30. package/dist/wake.d.ts +67 -0
  31. package/dist/wake.d.ts.map +1 -0
  32. package/dist/wake.js +234 -0
  33. package/dist/wake.js.map +1 -0
  34. package/openclaw.plugin.json +13 -12
  35. package/package.json +23 -5
  36. package/skills/brainstorm/SKILL.md +163 -0
  37. package/skills/chorus/SKILL.md +114 -97
  38. package/skills/develop/SKILL.md +197 -52
  39. package/skills/idea/SKILL.md +136 -150
  40. package/skills/openspec-aware/SKILL.md +425 -0
  41. package/skills/proposal/SKILL.md +162 -153
  42. package/skills/proposal-reviewer/SKILL.md +118 -0
  43. package/skills/quick-dev/SKILL.md +34 -10
  44. package/skills/review/SKILL.md +109 -35
  45. package/skills/task-reviewer/SKILL.md +113 -0
  46. package/skills/yolo/SKILL.md +501 -0
  47. package/src/commands.ts +138 -71
  48. package/src/config.ts +23 -10
  49. package/src/event-router.ts +46 -54
  50. package/src/index.ts +56 -83
  51. package/src/mcp-client.ts +17 -0
  52. package/src/mcp-registration.ts +142 -0
  53. package/src/openclaw-sdk.d.ts +95 -0
  54. package/src/wake.ts +310 -0
  55. package/src/tools/admin-tools.ts +0 -126
  56. package/src/tools/common-tools.ts +0 -575
  57. package/src/tools/dev-tools.ts +0 -105
  58. package/src/tools/pm-tools.ts +0 -411
package/README.md CHANGED
@@ -12,90 +12,74 @@
12
12
 
13
13
  OpenClaw plugin for [Chorus](https://github.com/Chorus-AIDLC/Chorus) — the AI-DLC (AI-Driven Development Lifecycle) collaboration platform.
14
14
 
15
- This plugin connects OpenClaw to Chorus via a persistent SSE connection and MCP tool bridge, enabling your OpenClaw agent to participate in the full Idea → Proposal → Task → Execute → Verify workflow autonomously.
15
+ This plugin lets an OpenClaw agent participate in the full Chorus Idea → Proposal → Task → Execute → Verify workflow. It does two things at activation:
16
16
 
17
- ## How It Works
17
+ 1. **Auto-registers the Chorus MCP server** in your OpenClaw config so the agent gains native `chorus__*` tools (no hand-wrapped tools — OpenClaw connects to Chorus over MCP directly).
18
+ 2. **Opens a persistent SSE connection** to Chorus and wakes the agent in-process (runs an embedded agent turn via `runEmbeddedAgent`) the moment a task is assigned, you are @mentioned, a proposal is approved/rejected, and more.
18
19
 
19
- ```
20
- Chorus Server
21
-
22
- ├── SSE (GET /api/events/notifications)
23
- │ Push real-time events: task_assigned, mentioned,
24
- │ proposal_rejected, elaboration_answered, etc.
25
- │ │
26
- │ ▼
27
- │ ┌──────────────────────┐
28
- │ │ SSE Listener │ ── auto-reconnect with
29
- │ │ (background service)│ exponential backoff
30
- │ └──────────┬───────────┘
31
- │ │
32
- │ ┌──────────▼───────────┐
33
- │ │ Event Router │ ── filters by project,
34
- │ │ │ maps event → action
35
- │ └──────────┬───────────┘
36
- │ │
37
- │ ┌──────────▼───────────┐ POST /hooks/wake
38
- │ │ Agent Trigger │ ──────────────────────► OpenClaw Agent
39
- │ └──────────────────────┘ (immediate heartbeat)
40
-
41
- ├── MCP (POST /api/mcp)
42
- │ 47 Chorus MCP tools available as native
43
- │ OpenClaw agent tools via @modelcontextprotocol/sdk
44
-
45
- └─────────────────────────────────────────────────────
46
- ```
47
-
48
- **Key design decisions:**
49
-
50
- - **MCP Client, not REST** — Uses `@modelcontextprotocol/sdk` to call Chorus MCP tools directly. Zero Chorus-side code changes needed. 47 tools registered out of the box. When Chorus adds new MCP tools, adding them to the plugin is a one-liner.
51
- - **SSE for push, MCP for pull** — SSE delivers real-time notifications; MCP handles all tool operations (claim, report, submit, etc.).
52
- - **Hooks-based agent wake** — Uses OpenClaw's `/hooks/wake` API to inject system events and trigger immediate heartbeats when Chorus events arrive.
20
+ It also ships **11 skills** — 9 workflow skills plus 2 read-only reviewer skills (`/proposal-reviewer`, `/task-reviewer`) that run inside spawned sub-agents.
53
21
 
54
- ## Prerequisites
22
+ > **Requires OpenClaw `>=2026.4.27`.** This package uses the OpenClaw Plugin SDK (`definePluginEntry` + native MCP auto-registration + `runEmbeddedAgent` wake + `activation.onStartup`). The binding floor is the newest API it depends on: `activation.onStartup` shipped in **2026.4.27** (`definePluginEntry` ~2026.3.28, `runEmbeddedAgent` 2026.4.10, `mutateConfigFile` 2026.4.26). The floor is enforced by `package.json` → `openclaw.compat.pluginApi` and `openclaw.install.minHostVersion` (both `>=2026.4.27`). On older hosts the SDK entry subpath / `activation.onStartup` are unavailable and the plugin will not load (or won't start its SSE service).
23
+ >
24
+ > **`activation.onStartup` is required.** This plugin has no channel or provider, so it would NOT be activated at gateway cold-boot without `activation: { onStartup: true }` in `openclaw.plugin.json`. That flag is what tells OpenClaw to import the plugin (and start its SSE service) on startup — without it the plugin shows as "enabled" but its background service never runs.
55
25
 
56
- - [OpenClaw](https://openclaw.ai) gateway running
57
- - [Chorus](https://github.com/Chorus-AIDLC/Chorus) server accessible
58
- - A Chorus API Key (`cho_` prefix) for the agent
59
- - OpenClaw hooks enabled (`hooks.enabled: true` in `openclaw.json`)
26
+ ---
60
27
 
61
28
  ## Installation
62
29
 
63
- ### 1. Install the plugin
30
+ ### From npm
64
31
 
65
32
  ```bash
66
- openclaw plugins install @chorus-aidlc/chorus-openclaw-plugin
33
+ openclaw plugins install npm:@chorus-aidlc/chorus-openclaw-plugin
34
+ openclaw plugins enable chorus-openclaw-plugin
67
35
  ```
68
36
 
69
- ### 2. Enable hooks
37
+ Restart the OpenClaw gateway if it was already running so it picks up the new plugin and the MCP server entry the plugin writes on first activation.
70
38
 
71
- Hooks are required for the agent wake mechanism. Add to your `~/.openclaw/openclaw.json`:
39
+ ### Local development (link the repo checkout)
72
40
 
73
- ```json
74
- {
75
- "hooks": {
76
- "enabled": true,
77
- "token": "your-hooks-token"
78
- }
79
- }
41
+ ```bash
42
+ # from the repo: packages/openclaw-plugin
43
+ openclaw plugins install --link . # link this directory instead of copying
44
+ openclaw plugins enable chorus-openclaw-plugin
80
45
  ```
81
46
 
82
- > The `hooks.token` must be different from `gateway.auth.token`.
47
+ A **linked** install does **not** need a build step. OpenClaw treats a linked
48
+ local plugin as a source checkout (`requireBuiltRuntimeEntry: false` — see
49
+ `src/plugins/discovery.ts`) and loads the TypeScript `extensions` entry
50
+ (`src/index.ts`) directly through its bundled `jiti` transpiler. `--link` keeps
51
+ OpenClaw pointed at your working tree, so editing `src/**` and restarting the
52
+ gateway picks up your changes without re-installing or recompiling.
53
+
54
+ > The compiled `dist/` is only required for the **npm-published** install path
55
+ > below — a copied/npm install sets `requireBuiltRuntimeEntry: true`, so OpenClaw
56
+ > demands the compiled runtime entry declared in `openclaw.runtimeExtensions`.
57
+ > Run `npm run build` before publishing (it also runs automatically via
58
+ > `prepublishOnly`). You do not need it for local `--link` development.
83
59
 
84
- ### 3. Configure the plugin
60
+ > The plugin id is **`chorus-openclaw-plugin`** — that is the argument to `enable` / `disable` / `uninstall`, and the key under `plugins.entries` in your config.
85
61
 
86
- Add the plugin entry to `~/.openclaw/openclaw.json`:
62
+ ---
63
+
64
+ ## Configuration
65
+
66
+ ### Where config lives
67
+
68
+ Plugin config lives in **`~/.openclaw/openclaw.json`** under:
69
+
70
+ ```
71
+ plugins.entries.chorus-openclaw-plugin.config
72
+ ```
87
73
 
88
74
  ```json
89
75
  {
90
76
  "plugins": {
91
- "enabled": true,
92
77
  "entries": {
93
78
  "chorus-openclaw-plugin": {
94
79
  "enabled": true,
95
80
  "config": {
96
81
  "chorusUrl": "https://chorus.example.com",
97
- "apiKey": "cho_your_api_key_here",
98
- "autoStart": true
82
+ "apiKey": "cho_your_api_key_here"
99
83
  }
100
84
  }
101
85
  }
@@ -103,277 +87,223 @@ Add the plugin entry to `~/.openclaw/openclaw.json`:
103
87
  }
104
88
  ```
105
89
 
106
- ## Configuration
90
+ ### Config keys
91
+
92
+ | Key | Type | Required | Default | What it does |
93
+ |-----|------|----------|---------|--------------|
94
+ | `chorusUrl` | `string` | **Yes** | — | Base URL of your Chorus server. The plugin derives the MCP endpoint (`<chorusUrl>/api/mcp`) and the SSE endpoint from it. |
95
+ | `apiKey` | `string` | **Yes** | — | Chorus API Key (`cho_` prefix). Used as the `Bearer` token for both the MCP server entry and the SSE connection. Marked `sensitive` in the UI hints. |
107
96
 
108
- | Field | Type | Required | Default | Description |
109
- |-------|------|----------|---------|-------------|
110
- | `chorusUrl` | `string` | Yes | — | Chorus server URL (e.g., `https://chorus.example.com`) |
111
- | `apiKey` | `string` | Yes | — | Chorus API Key with `cho_` prefix |
112
- | `projectUuids` | `string[]` | No | `[]` | Project UUIDs to monitor. Empty = all projects. |
113
- | `autoStart` | `boolean` | No | `true` | Auto-claim tasks when `task_assigned` events arrive |
97
+ If `chorusUrl` or `apiKey` is missing, the plugin logs a warning naming the missing field, skips MCP registration, and disables its features — it does not crash the gateway.
98
+
99
+ ---
100
+
101
+ ## How tools work now (native MCP)
102
+
103
+ On activation (full registration mode), the plugin **writes an `mcp.servers.chorus` entry** into your OpenClaw config via the host's `runtime.config.mutateConfigFile` API:
104
+
105
+ ```json
106
+ {
107
+ "mcp": {
108
+ "servers": {
109
+ "chorus": {
110
+ "url": "https://chorus.example.com/api/mcp",
111
+ "transport": "streamable-http",
112
+ "headers": { "Authorization": "Bearer cho_your_api_key_here" }
113
+ }
114
+ }
115
+ }
116
+ }
117
+ ```
118
+
119
+ OpenClaw then connects to the remote Chorus MCP server and **exposes every Chorus tool to the agent under the `chorus__` prefix** — for example `chorus__chorus_get_task`, `chorus__chorus_claim_task`, `chorus__chorus_submit_for_verify`. The plugin never re-declares those tools itself; they come straight from the MCP server.
120
+
121
+ The write is **idempotent**: if the existing entry already matches (same url + transport + Authorization), the plugin skips the write so it does not trigger a config reload on every activation. If `runtime.config.mutateConfigFile` is unavailable on the host, the failure is logged and swallowed — the SSE service and `/chorus` command still register.
122
+
123
+ ### Migration note: bare `chorus_*` tool names are gone
124
+
125
+ Earlier versions of this plugin **hand-wrapped** Chorus tools and exposed them to the agent under their bare names (`chorus_get_task`, `chorus_claim_task`, …). **Those registrations have been removed.** Tools now come from the auto-registered MCP server and are namespaced with the server id, so they appear as **`chorus__<tool>`** (double underscore).
126
+
127
+ If you have macros, prompts, or agent instructions that reference the bare names, update them:
128
+
129
+ ```
130
+ chorus_get_task → chorus__chorus_get_task
131
+ chorus_submit_for_verify → chorus__chorus_submit_for_verify
132
+ ```
133
+
134
+ (Inside the bundled skills and reviewer-agent prompts the tools are referred to by their logical Chorus names; OpenClaw resolves them through the MCP server.)
135
+
136
+ ### bundle-mcp sandbox caveat
137
+
138
+ When OpenClaw runs agents in a sandbox (`tools.sandbox.mode` = `"all"` or `"non-main"`), **MCP tools are owned by the built-in `bundle-mcp` plugin** and are filtered out of the agent's tool list by default. The `chorus__*` tools will be missing until you add either the `bundle-mcp` plugin or the `chorus__` glob to the sandbox allow list:
139
+
140
+ ```json
141
+ {
142
+ "tools": {
143
+ "sandbox": {
144
+ "tools": {
145
+ "alsoAllow": ["chorus__*"]
146
+ }
147
+ }
148
+ }
149
+ }
150
+ ```
114
151
 
115
- ### OpenClaw requirements
152
+ You can broaden this to `["bundle-mcp"]` to allow all MCP tools, or keep it scoped to `["chorus__*"]` to allow only Chorus tools. Restart the gateway after editing the sandbox policy. If you are **not** using sandbox mode, no allow-list change is needed.
116
153
 
117
- The plugin reads these from the main OpenClaw config:
154
+ ---
118
155
 
119
- - **`hooks.enabled`** must be `true` — required for agent wake via `/hooks/wake`
120
- - **`hooks.token`** — shared secret for hook authentication (must differ from `gateway.auth.token`)
121
- - **`gateway.port`** — defaults to `18789`
156
+ ## Real-time events (SSE agent wake)
122
157
 
123
- ## Features
158
+ The plugin runs a background service (`chorus-sse`) that holds an SSE connection to Chorus. When an event arrives it fetches the full notification over MCP and **wakes the main agent in-process** by running an embedded agent turn via the host's `runtime.agent.runEmbeddedAgent(...)`, with the event text as the turn's prompt. The turn runs on the main agent's existing session (so it has conversation context and the full `chorus__*` MCP tool set) and is headless (`disableMessageTool: true`) — the agent acts by calling Chorus MCP tools (e.g. `chorus_get_comments`, `chorus_add_comment`) rather than replying to a chat channel.
124
159
 
125
- ### Real-time SSE Events
160
+ > **Why not `enqueueSystemEvent`?** An earlier version pushed the wake text onto the session's system-event queue and triggered a heartbeat. That does **not** work for delivering content: the heartbeat prompt builder only renders exec-completion / cron events into a prompt, so a plain notification's queued text is never injected — the agent just runs the generic `[OpenClaw heartbeat poll]`. `runEmbeddedAgent` delivers the prompt directly.
126
161
 
127
- The plugin maintains a persistent SSE connection to Chorus and reacts to these events:
162
+ > **The configured model is passed explicitly.** `runEmbeddedAgent` does not auto-resolve the model from config; with no `provider`/`model` it falls back to the built-in default (`gpt-5.5`) and errors with "Unknown model". The plugin reads `agents.defaults.model` (`"provider/model"` or `{ primary: "provider/model" }`) and passes `provider` + `model` to each wake turn.
128
163
 
129
164
  | Event | Behavior |
130
165
  |-------|----------|
131
- | `task_assigned` | Auto-claim task (if `autoStart: true`) + wake agent to start work |
132
- | `mentioned` | Wake agent with @mention context |
133
- | `elaboration_requested` | Wake agent to review elaboration questions |
134
- | `elaboration_answered` | Wake agent to review answers, @mention answerer, then validate or start new round |
135
- | `proposal_rejected` | Wake agent with rejection reason to fix and resubmit, @mention reviewer |
136
- | `proposal_approved` | Wake agent to check newly created tasks, @mention approver |
137
- | `idea_claimed` | Wake agent when an idea is assigned to it, @mention assigner |
166
+ | `task_assigned` | Wake the agent to review the task and claim it (`chorus_claim_task`) when ready |
167
+ | `mentioned` | Wake the agent with the @mention context and a pointer to the conversation |
168
+ | `elaboration_requested` | Wake the agent to review elaboration questions |
169
+ | `elaboration_answered` | Wake the agent to review answers, then validate or open another round |
170
+ | `proposal_rejected` | Wake the agent with the rejection note to fix and resubmit |
171
+ | `proposal_approved` | Wake the agent to pick up the newly created tasks |
172
+ | `idea_claimed` | Wake the agent when an idea is assigned to it |
173
+ | `task_verified` | Wake the agent to check for newly unblocked tasks |
174
+ | `task_reopened` | Wake the agent with verification feedback to rework |
175
+
176
+ **Resilience.** The SSE listener auto-reconnects with exponential backoff (1s → 2s → … → 30s max). After a reconnect it back-fills unread notifications over MCP so nothing is lost while disconnected. If no main agent session key can be resolved, `runEmbeddedAgent` is unavailable on the host, or a wake turn rejects (e.g. a turn is already in flight), the individual wake is **dropped with a warning** — it never throws and never crashes the SSE service. The next SSE event re-triggers.
177
+
178
+ ---
179
+
180
+ ## Skills (11)
181
+
182
+ Skills are bundled under `skills/` and auto-discovered by OpenClaw. On OpenClaw a skill is invoked as a **bare slash command of its name** — e.g. `/develop`, `/idea` (OpenClaw does **not** use a `chorus:` namespace prefix).
138
183
 
139
- **Resilience:** Exponential backoff reconnect (1s 2s → 4s → ... → 30s max). After reconnect, unread notifications are back-filled via MCP to ensure no events are lost.
184
+ | Skill | Invoke | Description |
185
+ |-------|--------|-------------|
186
+ | `chorus` | `/chorus` | Platform overview, common tools, setup, and routing to the stage-specific skills |
187
+ | `idea` | `/idea` | Claim ideas, run elaboration rounds, and prepare for proposal creation |
188
+ | `brainstorm` | `/brainstorm` | Optional divergent-then-convergent dialogue for fuzzy ideas (prelude to elaboration) |
189
+ | `proposal` | `/proposal` | Create proposals with document + task drafts, manage the dependency DAG, validate and submit |
190
+ | `develop` | `/develop` | Claim tasks, report work, manage sessions, and run wave-based execution |
191
+ | `quick-dev` | `/quick-dev` | Skip Idea→Proposal — create tasks directly, execute, and verify |
192
+ | `review` | `/review` | Approve/reject proposals, verify tasks, and manage project governance |
193
+ | `yolo` | `/yolo` | Full-auto AI-DLC pipeline — from prompt to done |
194
+ | `openspec-aware` | `/openspec-aware` | Opt-in OpenSpec authoring for PM workflows when the local `openspec` CLI is present |
195
+ | `proposal-reviewer` | `/proposal-reviewer` | Read-only adversarial proposal review; ends with a `VERDICT:` comment |
196
+ | `task-reviewer` | `/task-reviewer` | Read-only adversarial task verification (read-only bash for tests); ends with a `VERDICT:` comment |
140
197
 
141
- ### Built-in Skills (6)
198
+ > Note: `/chorus` (the bare skill) and the `/chorus <subcommand>` command share the same `chorus` prefix. `/chorus status|tasks|ideas|skills` are fast, LLM-free status queries handled by the plugin command (see below); `/chorus` with no recognized subcommand falls through to the command's help/status.
142
199
 
143
- The plugin ships with 6 SKILL.md files that OpenClaw auto-discovers and loads. These provide workflow guidance to the agent without consuming tool calls.
200
+ ## Reviewer skills (2)
201
+
202
+ `proposal-reviewer` and `task-reviewer` are bundled **as skills** (not agent definitions — OpenClaw has no Claude-Code-style typed agents). Both are **read-only** and end by posting a structured `VERDICT:` comment.
203
+
204
+ They are meant to run inside a **spawned sub-agent**: the orchestrating skill (`/proposal`, `/develop`, `/yolo`, `/review`) uses the OpenClaw `sessions_spawn` tool to spawn a sub-agent and instructs it (in the spawn `task`) to invoke `/proposal-reviewer` or `/task-reviewer` against the entity, then waits for the VERDICT. Spawned sub-agents inherit the plugin's skill snapshot, so the slash-commands are available to them. If `sessions_spawn` is unavailable, the orchestrator runs the same review itself as a read-only pass (the reviewer skills are the authoritative checklists).
144
205
 
145
206
  | Skill | Description |
146
207
  |-------|-------------|
147
- | `chorus` | Platform overview, common tools, setup, and workflow routing |
148
- | `idea` | Claim ideas, run elaboration rounds, prepare for proposal |
149
- | `proposal` | Create proposals with document & task drafts, manage dependency DAG |
150
- | `develop` | Claim tasks, report work, submit for verification |
151
- | `quick-dev` | Skip Idea→Proposal, create tasks directly, execute, and verify |
152
- | `review` | Approve/reject proposals, verify tasks, project governance |
153
-
154
- Skills are automatically available when the plugin is enabled no extra configuration needed.
155
-
156
- ### Registered Tools (47 total)
157
-
158
- #### PM Workflow (17 tools)
159
-
160
- | Tool | Description |
161
- |------|-------------|
162
- | `chorus_claim_idea` | Claim an open idea for elaboration |
163
- | `chorus_start_elaboration` | Start elaboration round with structured questions |
164
- | `chorus_answer_elaboration` | Submit answers for elaboration round |
165
- | `chorus_validate_elaboration` | Validate answers, resolve or request follow-up |
166
- | `chorus_create_proposal` | Create proposal with document + task drafts |
167
- | `chorus_add_document_draft` | Add document draft to proposal |
168
- | `chorus_add_task_draft` | Add task draft to proposal |
169
- | `chorus_get_proposal` | View full proposal with all draft UUIDs |
170
- | `chorus_update_document_draft` | Modify document draft |
171
- | `chorus_update_task_draft` | Modify task draft (including dependencies) |
172
- | `chorus_remove_document_draft` | Remove document draft |
173
- | `chorus_remove_task_draft` | Remove task draft |
174
- | `chorus_validate_proposal` | Check proposal completeness before submit |
175
- | `chorus_submit_proposal` | Submit proposal for approval |
176
- | `chorus_pm_create_idea` | Create a new idea in a project |
177
- | `chorus_pm_assign_task` | Assign a task to a specific Developer Agent |
178
- | `chorus_move_idea` | Move an idea to a different project |
179
-
180
- #### Developer Workflow (4 tools)
181
-
182
- | Tool | Description |
183
- |------|-------------|
184
- | `chorus_claim_task` | Claim an open task |
185
- | `chorus_update_task` | Update task status or fields (title, description, priority, dependencies) |
186
- | `chorus_report_work` | Report work progress (writes comment + records activity) |
187
- | `chorus_submit_for_verify` | Submit completed task for verification |
188
- | `chorus_report_criteria_self_check` | Self-check acceptance criteria before submitting |
189
-
190
- #### Common & Exploration (21 tools)
191
-
192
- | Tool | Description |
193
- |------|-------------|
194
- | `chorus_checkin` | Agent check-in (identity, owner info, roles, assignments) |
195
- | `chorus_get_notifications` | Fetch notifications (default: unread) |
196
- | `chorus_get_project` | Get project details |
197
- | `chorus_get_task` | Get task details |
198
- | `chorus_get_idea` | Get idea details |
199
- | `chorus_get_available_tasks` | List open tasks in a project |
200
- | `chorus_get_available_ideas` | List open ideas in a project |
201
- | `chorus_add_comment` | Comment on idea/proposal/task/document |
202
- | `chorus_search_mentionables` | Search for @mentionable users and agents |
203
- | `chorus_list_projects` | List all projects |
204
- | `chorus_list_tasks` | List tasks in a project (filterable by status/priority) |
205
- | `chorus_get_ideas` | List ideas in a project (filterable by status) |
206
- | `chorus_get_proposals` | List proposals in a project |
207
- | `chorus_get_documents` | List documents in a project |
208
- | `chorus_get_document` | Get full document content |
209
- | `chorus_get_unblocked_tasks` | List tasks ready to start (dependencies resolved) |
210
- | `chorus_get_activity` | Get project activity stream |
211
- | `chorus_get_comments` | Get comments on an entity |
212
- | `chorus_get_elaboration` | Get full elaboration state for an idea |
213
- | `chorus_get_my_assignments` | Get all claimed ideas and tasks |
214
- | `chorus_get_project_groups` | List all project groups |
215
- | `chorus_get_project_group` | Get a project group with its projects |
216
- | `chorus_create_tasks` | Batch create tasks (Quick Task or Proposal-linked) |
217
- | `chorus_search` | Search across tasks, ideas, proposals, documents, projects |
218
-
219
- #### Admin (5 tools)
220
-
221
- | Tool | Description |
222
- |------|-------------|
223
- | `chorus_admin_create_project` | Create a new project |
224
- | `chorus_admin_create_project_group` | Create a new project group |
225
- | `chorus_admin_approve_proposal` | Approve a proposal (materializes drafts into Documents + Tasks) |
226
- | `chorus_admin_verify_task` | Verify a task (to_verify → done, unblocks downstream) |
227
- | `chorus_mark_acceptance_criteria` | Mark acceptance criteria as passed/failed |
228
-
229
- ### Commands
230
-
231
- Bypass LLM for fast status queries:
208
+ | `/proposal-reviewer` | Reviews submitted proposals — document completeness, task granularity, AC alignment, cross-task dependencies. No Bash. |
209
+ | `/task-reviewer` | Verifies submitted tasks against the AC and proposal documents. Read-only Bash allowed for verification only (tests/build, `cat`/`grep`/`ls`, `git diff`/`log`/`show`). |
210
+
211
+ ---
212
+
213
+ ## Commands
214
+
215
+ `/chorus` runs fast, LLM-free status queries through the plugin's own slim MCP client:
232
216
 
233
217
  | Command | Description |
234
218
  |---------|-------------|
235
- | `/chorus` or `/chorus status` | Connection status, assignments, unread count |
219
+ | `/chorus` or `/chorus status` | Connection status, agent identity, assigned-idea count, unread notifications, skill list |
236
220
  | `/chorus tasks` | List your assigned tasks |
237
221
  | `/chorus ideas` | List your assigned ideas |
238
- | `/chorus skills` | List available Chorus skills |
222
+ | `/chorus skills` | List the 9 bundled Chorus skills |
223
+
224
+ ---
239
225
 
240
226
  ## Architecture
241
227
 
242
228
  ```
243
229
  packages/openclaw-plugin/
244
- ├── package.json # npm package config
245
- ├── openclaw.plugin.json # OpenClaw plugin manifest (declares skills)
246
- ├── tsconfig.json
247
- ├── skills/ # 6 SKILL.md files (auto-discovered by OpenClaw)
248
- ├── chorus/SKILL.md # Core overview & routing
249
- │ ├── idea/SKILL.md # Idea → Elaboration workflow
250
- │ ├── proposal/SKILL.md # Proposal → DAG → Submit workflow
251
- │ ├── develop/SKILL.md # Task → Report → Verify workflow
252
- │ ├── quick-dev/SKILL.md # Quick task creation & execution
253
- │ └── review/SKILL.md # Admin review & governance
230
+ ├── package.json # npm + openclaw block (extensions / runtimeExtensions, install, compat)
231
+ ├── openclaw.plugin.json # plugin manifest (id, activation.onStartup, configSchema, skills dir, uiHints)
232
+ ├── tsconfig.json # build config; excludes __tests__ from dist
233
+ ├── vitest.config.ts # standalone test runner config (package is outside the root workspace)
234
+ ├── skills/ # 11 SKILL.md skills (9 workflow + proposal-reviewer + task-reviewer), auto-discovered
254
235
  └── src/
255
- ├── index.ts # Plugin entry — wires all modules together
256
- ├── config.ts # Zod config schema
257
- ├── mcp-client.ts # MCP Client (lazy connect + 404 auto-reconnect)
258
- ├── sse-listener.ts # SSE long-lived connection + reconnect
259
- ├── event-router.ts # Event agent action mapping
260
- ├── commands.ts # /chorus commands
261
- └── tools/
262
- ├── pm-tools.ts # 17 PM workflow tools
263
- ├── dev-tools.ts # 4 Developer tools
264
- ├── common-tools.ts # 21 common/exploration tools
265
- └── admin-tools.ts # 5 Admin tools
236
+ ├── index.ts # definePluginEntry — wires everything; gated to "full" registration mode
237
+ ├── config.ts # config contract (chorusUrl, apiKey) + location constants
238
+ ├── mcp-registration.ts # writes mcp.servers.chorus (idempotent, streamable-http + Bearer)
239
+ ├── mcp-client.ts # slim MCP client for the plugin's own calls (checkin, assignments, claim)
240
+ ├── sse-listener.ts # SSE connection + exponential-backoff reconnect
241
+ ├── event-router.ts # SSE event → wake-message mapping (project-filtered)
242
+ ├── wake.ts # resolves main session + model, runs an embedded agent turn (runEmbeddedAgent)
243
+ ├── commands.ts # /chorus status|tasks|ideas|skills
244
+ ├── openclaw-sdk.d.ts # ambient SDK shim (compile-time only; see below)
245
+ └── __tests__/ # vitest unit tests (config, mcp-registration, wake, event-router, commands, sse-listener)
266
246
  ```
267
247
 
268
- ### MCP Client (`mcp-client.ts`)
269
-
270
- Wraps `@modelcontextprotocol/sdk` with:
271
- - **Lazy connection** — connects on first `callTool()`, not at startup
272
- - **Auto-reconnect** — detects 404 (session expired), reconnects, retries the call
273
- - **Status tracking** — `connected | disconnected | connecting | reconnecting`
274
-
275
- ### SSE Listener (`sse-listener.ts`)
276
-
277
- - Native `fetch()` + `ReadableStream` (not browser EventSource — allows `Authorization` header)
278
- - `Authorization: Bearer cho_xxx` authentication
279
- - SSE protocol parsing (`data:` lines → JSON, `:` heartbeat lines ignored)
280
- - Exponential backoff: 1s → 2s → 4s → 8s → 16s → 30s (max)
281
- - Calls `onReconnect()` after successful reconnect for notification back-fill
248
+ ### Note on `openclaw-sdk.d.ts`
282
249
 
283
- ### Event Router (`event-router.ts`)
250
+ The entry imports `definePluginEntry` from `openclaw/plugin-sdk/plugin-entry`, a subpath available in OpenClaw `>=2026.4.27` (the plugin's host floor). When the locally resolvable `openclaw` package is an older build, `tsc` cannot resolve that subpath, so `src/openclaw-sdk.d.ts` declares a minimal ambient module to satisfy the type-checker. It is **compile-time only** — at install/runtime the real host (`>=2026.4.27`) provides the actual SDK. The floor is enforced at install time by `openclaw.compat.pluginApi >=2026.4.27` (and `openclaw.install.minHostVersion`); `peerDependencies.openclaw >=2026.0.0` is npm metadata only and is intentionally looser. Once the workspace resolves a `>=2026.4.27` `openclaw` build, delete the shim and rely on the real types.
284
251
 
285
- - Fetches full notification details via MCP (SSE only sends minimal envelope)
286
- - Filters by `projectUuids` config
287
- - Routes by notification `action` type
288
- - All handlers catch errors internally — never crashes the gateway
289
-
290
- ## Troubleshooting
252
+ ---
291
253
 
292
- ### chorus_* tools not available in agent (sandbox mode)
254
+ ## Validation / Release checklist
293
255
 
294
- **Symptom:** Agent cannot call `chorus_checkin` or any `chorus_*` tool. Tools are missing from the tool list.
256
+ The maintainer release gate has four parts. The first (type check + test + build) runs anywhere with Node + the dev dependencies. The last two (SDK validators + smoke) require an installed `openclaw` >=2026.4.27 CLI and a running host.
295
257
 
296
- **Cause:** When OpenClaw sandbox mode is enabled (`agents.defaults.sandbox.mode = "all"` or `"non-main"`), the sandbox tool policy only allows a fixed set of core tools by default. Plugin-registered tools are excluded unless explicitly allowed.
258
+ ### 1. Type check, test & build (no OpenClaw CLI required)
297
259
 
298
- **Verify:**
299
260
  ```bash
300
- openclaw sandbox explain
301
- # Look for: Sandbox tool policy allow (default)
302
- # chorus_* tools will NOT appear unless configured
261
+ npm run typecheck # tsc --noEmit → exit 0, no diagnostics
262
+ npm run test # vitest run → exit 0, all unit tests pass
263
+ npm run build # tsc → exit 0, writes dist/index.js
303
264
  ```
304
265
 
305
- **Fix:** Add the plugin to the sandbox tool allow list:
306
- ```bash
307
- openclaw config set tools.sandbox.tools.alsoAllow '["chorus-openclaw-plugin"]'
308
- # Then restart gateway
309
- openclaw gateway restart
310
- ```
266
+ These three also run automatically before publish via the `prepublishOnly`
267
+ script (`clean → typecheck → test → build`), so `npm publish` cannot ship a
268
+ package that fails to type-check, fails its tests, or is missing the compiled
269
+ `dist/`. Publishing the compiled runtime is **mandatory** for the npm install
270
+ path a copied/npm install rejects a TypeScript-only entry with *"requires
271
+ compiled runtime output"* (see the local-development note above).
311
272
 
312
- Or add directly to `~/.openclaw/openclaw.json`:
313
- ```json
314
- {
315
- "tools": {
316
- "sandbox": {
317
- "tools": {
318
- "alsoAllow": ["chorus-openclaw-plugin"]
319
- }
320
- }
321
- }
322
- }
323
- ```
273
+ `dist/index.js` must exist and its **default export** must be the `definePluginEntry(...)` result — an object with `id: "chorus-openclaw-plugin"` and a `register` function. A direct `import('./dist/index.js')` resolves the `openclaw/plugin-sdk/plugin-entry` peer subpath, so run this on a host where a >=2026.4.27 `openclaw` package is resolvable.
324
274
 
325
- ---
275
+ ### 2. OpenClaw SDK validators (require `openclaw` >=2026.4.27 CLI)
326
276
 
327
- ### "plugin id mismatch" warning
328
- Ensure `openclaw.plugin.json` `id` and `index.ts` `id` both equal `chorus-openclaw-plugin`.
277
+ Run from the package root after `npm run build`:
329
278
 
330
- ### "Wake agent failed: HTTP 405"
331
- Hooks are not enabled. Add to `openclaw.json`:
332
- ```json
333
- { "hooks": { "enabled": true, "token": "your-distinct-token" } }
279
+ ```bash
280
+ openclaw plugins build --entry ./dist/index.js --check # expect exit 0: "Plugin metadata is up to date."
281
+ openclaw plugins validate --entry ./dist/index.js # expect exit 0: "Plugin chorus-openclaw-plugin is valid."
334
282
  ```
335
- The `hooks.token` must be different from `gateway.auth.token`.
336
283
 
337
- ### "Cannot wake agent gateway.auth.token not configured"
338
- The plugin couldn't read `hooks.token` from OpenClaw config. Verify your `openclaw.json` has the `hooks` section.
284
+ - `plugins build --check` fails (exit 1, "Generated plugin metadata is out of date. Run openclaw plugins build.") if the committed `openclaw.plugin.json` / `package.json` metadata is stale relative to the entry. If it fails, run `openclaw plugins build` (no `--check`) to regenerate, review the diff, and commit.
285
+ - `plugins validate` loads the manifest, checks the entry id matches the manifest id, confirms the `configSchema` is present, and verifies `package.json` `openclaw.extensions` includes the entry. Expected success: `Plugin chorus-openclaw-plugin is valid.`
339
286
 
340
- ### Tools return "undefined" parameters
341
- OpenClaw tool `execute` signature is `execute(toolCallId, params)` — the first argument is the call ID, not the params object. If you see this, check that all tools use `execute(_id, { param1, param2 })`.
287
+ ### 3. Manual smoke test (require `openclaw` >=2026.4.27 host)
342
288
 
343
- ### Bedrock "inputSchema.json.type must be object"
344
- All tool `parameters` must be full JSON Schema with `type: "object"` at the top level, not shorthand `{ key: { type: "string" } }`.
289
+ ```bash
290
+ openclaw plugins install --link .
291
+ openclaw plugins enable chorus-openclaw-plugin
292
+ # configure plugins.entries.chorus-openclaw-plugin.config (chorusUrl + apiKey), then restart the gateway
293
+ ```
345
294
 
346
- ## Appendix: Local Development Install
295
+ Confirm:
347
296
 
348
- If you're developing the plugin from the Chorus repo source:
297
+ 1. **`mcp.servers.chorus` is written** inspect `~/.openclaw/openclaw.json`; the `mcp.servers.chorus` entry should have `url: <chorusUrl>/api/mcp`, `transport: "streamable-http"`, and a `Bearer` Authorization header.
298
+ 2. **`chorus__*` tools appear** — the agent's tool list includes `chorus__chorus_get_task`, `chorus__chorus_checkin`, etc. (in sandbox mode, after adding `chorus__*` to `tools.sandbox.tools.alsoAllow`).
299
+ 3. **SSE wake fires** — assign a Chorus task to this agent; the SSE event should wake the agent in-process. Check the gateway log for `[Chorus] Wake enqueued`.
300
+ 4. **`/chorus status` works** — running `/chorus` returns connection status + checkin data (agent name, assigned-idea count, unread notifications, skill list).
349
301
 
350
- ```bash
351
- # No build needed — OpenClaw loads .ts files directly via jiti
352
- cd /path/to/Chorus/packages/openclaw-plugin
353
- ```
302
+ ### Status in this repo's CI environment
354
303
 
355
- Add to `~/.openclaw/openclaw.json`:
304
+ In the repository CI/dev environment the `openclaw` CLI is **not installed** (and the resolvable `openclaw` peer is an older `2026.3.x` build, which is exactly why the `openclaw-sdk.d.ts` shim is still required), so steps 2–3 above cannot be executed here. Section 1 (`tsc --noEmit`, `vitest run`, and `tsc` build → `dist/index.js` with a valid default export) **is** run and must pass. A maintainer on a >=2026.4.27 host must run sections 2 and 3 before publishing and confirm the expected exit codes / messages above.
356
305
 
357
- ```json
358
- {
359
- "plugins": {
360
- "enabled": true,
361
- "load": {
362
- "paths": ["/path/to/Chorus/packages/openclaw-plugin"]
363
- },
364
- "entries": {
365
- "chorus-openclaw-plugin": {
366
- "enabled": true,
367
- "config": {
368
- "chorusUrl": "http://localhost:3000",
369
- "apiKey": "cho_your_dev_key",
370
- "autoStart": true
371
- }
372
- }
373
- }
374
- }
375
- }
376
- ```
306
+ ---
377
307
 
378
308
  ## License
379
309
 
@@ -0,0 +1,5 @@
1
+ import type { ChorusMcpClient } from "./mcp-client.js";
2
+ export declare function registerChorusCommands(api: {
3
+ registerCommand: (command: unknown) => void;
4
+ }, mcpClient: ChorusMcpClient, getStatus: () => string): void;
5
+ //# sourceMappingURL=commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AA6KvD,wBAAgB,sBAAsB,CACpC,GAAG,EAAE;IAAE,eAAe,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;CAAE,EACpD,SAAS,EAAE,eAAe,EAC1B,SAAS,EAAE,MAAM,MAAM,GACtB,IAAI,CAqDN"}