@chorus-aidlc/chorus-openclaw-plugin 0.3.1 → 0.5.0

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 +218 -218
  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 +14 -12
  35. package/package.json +24 -5
  36. package/skills/brainstorm/SKILL.md +163 -0
  37. package/skills/chorus/SKILL.md +413 -0
  38. package/skills/develop/SKILL.md +434 -0
  39. package/skills/idea/SKILL.md +293 -0
  40. package/skills/openspec-aware/SKILL.md +425 -0
  41. package/skills/proposal/SKILL.md +397 -0
  42. package/skills/proposal-reviewer/SKILL.md +117 -0
  43. package/skills/quick-dev/SKILL.md +198 -0
  44. package/skills/review/SKILL.md +354 -0
  45. package/skills/task-reviewer/SKILL.md +113 -0
  46. package/skills/yolo/SKILL.md +498 -0
  47. package/src/commands.ts +147 -57
  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 -117
  56. package/src/tools/common-tools.ts +0 -546
  57. package/src/tools/dev-tools.ts +0 -97
  58. package/src/tools/pm-tools.ts +0 -390
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
- │ 40 Chorus MCP tools available as native
43
- │ OpenClaw agent tools via @modelcontextprotocol/sdk
44
-
45
- └─────────────────────────────────────────────────────
46
- ```
47
-
48
- **Key design decisions:**
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.
49
21
 
50
- - **MCP Client, not REST** Uses `@modelcontextprotocol/sdk` to call Chorus MCP tools directly. Zero Chorus-side code changes needed. 40 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.
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.
53
25
 
54
- ## Prerequisites
55
-
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.
59
+
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.
83
61
 
84
- ### 3. Configure the plugin
62
+ ---
85
63
 
86
- Add the plugin entry to `~/.openclaw/openclaw.json`:
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,207 +87,223 @@ Add the plugin entry to `~/.openclaw/openclaw.json`:
103
87
  }
104
88
  ```
105
89
 
106
- ## Configuration
90
+ ### Config keys
107
91
 
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 |
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. |
114
96
 
115
- ### OpenClaw requirements
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.
116
98
 
117
- The plugin reads these from the main OpenClaw config:
99
+ ---
118
100
 
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`
101
+ ## How tools work now (native MCP)
122
102
 
123
- ## Features
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:
124
104
 
125
- ### Real-time SSE Events
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
+ ```
126
133
 
127
- The plugin maintains a persistent SSE connection to Chorus and reacts to these events:
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
+ ```
151
+
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.
153
+
154
+ ---
155
+
156
+ ## Real-time events (SSE → agent wake)
157
+
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.
159
+
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.
161
+
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 |
138
-
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.
140
-
141
- ### Registered Tools (40 total)
142
-
143
- #### PM Workflow (15 tools)
144
-
145
- | Tool | Description |
146
- |------|-------------|
147
- | `chorus_claim_idea` | Claim an open idea for elaboration |
148
- | `chorus_start_elaboration` | Start elaboration round with structured questions |
149
- | `chorus_answer_elaboration` | Submit answers for elaboration round |
150
- | `chorus_validate_elaboration` | Validate answers, resolve or request follow-up |
151
- | `chorus_create_proposal` | Create proposal with document + task drafts |
152
- | `chorus_add_document_draft` | Add document draft to proposal |
153
- | `chorus_add_task_draft` | Add task draft to proposal |
154
- | `chorus_get_proposal` | View full proposal with all draft UUIDs |
155
- | `chorus_update_document_draft` | Modify document draft |
156
- | `chorus_update_task_draft` | Modify task draft (including dependencies) |
157
- | `chorus_remove_document_draft` | Remove document draft |
158
- | `chorus_remove_task_draft` | Remove task draft |
159
- | `chorus_validate_proposal` | Check proposal completeness before submit |
160
- | `chorus_submit_proposal` | Submit proposal for approval |
161
- | `chorus_pm_create_idea` | Create a new idea in a project |
162
-
163
- #### Developer Workflow (4 tools)
164
-
165
- | Tool | Description |
166
- |------|-------------|
167
- | `chorus_claim_task` | Claim an open task |
168
- | `chorus_update_task` | Update task status (in_progress / to_verify) |
169
- | `chorus_report_work` | Report work progress |
170
- | `chorus_submit_for_verify` | Submit completed task for verification |
171
-
172
- #### Common & Exploration (20 tools)
173
-
174
- | Tool | Description |
175
- |------|-------------|
176
- | `chorus_checkin` | Agent check-in (identity, owner info, roles, assignments) |
177
- | `chorus_get_notifications` | Fetch notifications (default: unread) |
178
- | `chorus_get_project` | Get project details |
179
- | `chorus_get_task` | Get task details |
180
- | `chorus_get_idea` | Get idea details |
181
- | `chorus_get_available_tasks` | List open tasks in a project |
182
- | `chorus_get_available_ideas` | List open ideas in a project |
183
- | `chorus_add_comment` | Comment on idea/proposal/task/document |
184
- | `chorus_search_mentionables` | Search for @mentionable users and agents |
185
- | `chorus_list_projects` | List all projects |
186
- | `chorus_list_tasks` | List tasks in a project (filterable by status/priority) |
187
- | `chorus_get_ideas` | List ideas in a project (filterable by status) |
188
- | `chorus_get_proposals` | List proposals in a project |
189
- | `chorus_get_documents` | List documents in a project |
190
- | `chorus_get_document` | Get full document content |
191
- | `chorus_get_unblocked_tasks` | List tasks ready to start (dependencies resolved) |
192
- | `chorus_get_activity` | Get project activity stream |
193
- | `chorus_get_comments` | Get comments on an entity |
194
- | `chorus_get_elaboration` | Get full elaboration state for an idea |
195
- | `chorus_get_my_assignments` | Get all claimed ideas and tasks |
196
-
197
- #### Admin (1 tool)
198
-
199
- | Tool | Description |
200
- |------|-------------|
201
- | `chorus_admin_create_project` | Create a new project |
202
-
203
- ### Commands
204
-
205
- Bypass LLM for fast status queries:
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).
183
+
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 |
197
+
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.
199
+
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).
205
+
206
+ | Skill | Description |
207
+ |-------|-------------|
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:
206
216
 
207
217
  | Command | Description |
208
218
  |---------|-------------|
209
- | `/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 |
210
220
  | `/chorus tasks` | List your assigned tasks |
211
221
  | `/chorus ideas` | List your assigned ideas |
222
+ | `/chorus skills` | List the 9 bundled Chorus skills |
223
+
224
+ ---
212
225
 
213
226
  ## Architecture
214
227
 
215
228
  ```
216
229
  packages/openclaw-plugin/
217
- ├── package.json # npm package config
218
- ├── openclaw.plugin.json # OpenClaw plugin manifest
219
- ├── tsconfig.json
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
220
235
  └── src/
221
- ├── index.ts # Plugin entry — wires all modules together
222
- ├── config.ts # Zod config schema
223
- ├── mcp-client.ts # MCP Client (lazy connect + 404 auto-reconnect)
224
- ├── sse-listener.ts # SSE long-lived connection + reconnect
225
- ├── event-router.ts # Event agent action mapping
226
- ├── commands.ts # /chorus commands
227
- └── tools/
228
- ├── pm-tools.ts # 14 PM workflow tools
229
- ├── dev-tools.ts # 4 Developer tools
230
- └── common-tools.ts # 21 common/exploration/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)
231
246
  ```
232
247
 
233
- ### MCP Client (`mcp-client.ts`)
248
+ ### Note on `openclaw-sdk.d.ts`
234
249
 
235
- Wraps `@modelcontextprotocol/sdk` with:
236
- - **Lazy connection** — connects on first `callTool()`, not at startup
237
- - **Auto-reconnect** — detects 404 (session expired), reconnects, retries the call
238
- - **Status tracking** — `connected | disconnected | connecting | reconnecting`
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.
239
251
 
240
- ### SSE Listener (`sse-listener.ts`)
252
+ ---
241
253
 
242
- - Native `fetch()` + `ReadableStream` (not browser EventSource — allows `Authorization` header)
243
- - `Authorization: Bearer cho_xxx` authentication
244
- - SSE protocol parsing (`data:` lines → JSON, `:` heartbeat lines ignored)
245
- - Exponential backoff: 1s → 2s → 4s → 8s → 16s → 30s (max)
246
- - Calls `onReconnect()` after successful reconnect for notification back-fill
254
+ ## Validation / Release checklist
247
255
 
248
- ### Event Router (`event-router.ts`)
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.
249
257
 
250
- - Fetches full notification details via MCP (SSE only sends minimal envelope)
251
- - Filters by `projectUuids` config
252
- - Routes by notification `action` type
253
- - All handlers catch errors internally — never crashes the gateway
258
+ ### 1. Type check, test & build (no OpenClaw CLI required)
254
259
 
255
- ## Troubleshooting
260
+ ```bash
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
264
+ ```
256
265
 
257
- ### "plugin id mismatch" warning
258
- Ensure `openclaw.plugin.json` `id` and `index.ts` `id` both equal `chorus-openclaw-plugin`.
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).
259
272
 
260
- ### "Wake agent failed: HTTP 405"
261
- Hooks are not enabled. Add to `openclaw.json`:
262
- ```json
263
- { "hooks": { "enabled": true, "token": "your-distinct-token" } }
264
- ```
265
- The `hooks.token` must be different from `gateway.auth.token`.
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.
266
274
 
267
- ### "Cannot wake agent gateway.auth.token not configured"
268
- The plugin couldn't read `hooks.token` from OpenClaw config. Verify your `openclaw.json` has the `hooks` section.
275
+ ### 2. OpenClaw SDK validators (require `openclaw` >=2026.4.27 CLI)
269
276
 
270
- ### Tools return "undefined" parameters
271
- 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 })`.
277
+ Run from the package root after `npm run build`:
272
278
 
273
- ### Bedrock "inputSchema.json.type must be object"
274
- All tool `parameters` must be full JSON Schema with `type: "object"` at the top level, not shorthand `{ key: { type: "string" } }`.
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."
282
+ ```
275
283
 
276
- ## Appendix: Local Development Install
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.`
277
286
 
278
- If you're developing the plugin from the Chorus repo source:
287
+ ### 3. Manual smoke test (require `openclaw` >=2026.4.27 host)
279
288
 
280
289
  ```bash
281
- # No build needed — OpenClaw loads .ts files directly via jiti
282
- cd /path/to/Chorus/packages/openclaw-plugin
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
283
293
  ```
284
294
 
285
- Add to `~/.openclaw/openclaw.json`:
295
+ Confirm:
286
296
 
287
- ```json
288
- {
289
- "plugins": {
290
- "enabled": true,
291
- "load": {
292
- "paths": ["/path/to/Chorus/packages/openclaw-plugin"]
293
- },
294
- "entries": {
295
- "chorus-openclaw-plugin": {
296
- "enabled": true,
297
- "config": {
298
- "chorusUrl": "http://localhost:3000",
299
- "apiKey": "cho_your_dev_key",
300
- "autoStart": true
301
- }
302
- }
303
- }
304
- }
305
- }
306
- ```
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).
301
+
302
+ ### Status in this repo's CI environment
303
+
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.
305
+
306
+ ---
307
307
 
308
308
  ## License
309
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"}