@chorus-aidlc/chorus-openclaw-plugin 0.1.7 → 0.2.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.
- package/package.json +1 -1
- package/src/event-router.ts +24 -0
- package/src/tools/common-tools.ts +1 -1
- package/src/tools/dev-tools.ts +61 -1
- package/src/tools/pm-tools.ts +7 -7
package/package.json
CHANGED
package/src/event-router.ts
CHANGED
|
@@ -120,6 +120,12 @@ export class ChorusEventRouter {
|
|
|
120
120
|
case "idea_claimed":
|
|
121
121
|
this.handleIdeaClaimed(notification);
|
|
122
122
|
break;
|
|
123
|
+
case "task_verified":
|
|
124
|
+
this.handleTaskVerified(notification);
|
|
125
|
+
break;
|
|
126
|
+
case "task_reopened":
|
|
127
|
+
this.handleTaskReopened(notification);
|
|
128
|
+
break;
|
|
123
129
|
default:
|
|
124
130
|
this.logger.info(`Unhandled notification action: "${notification.action}"`);
|
|
125
131
|
break;
|
|
@@ -217,6 +223,24 @@ export class ChorusEventRouter {
|
|
|
217
223
|
);
|
|
218
224
|
}
|
|
219
225
|
|
|
226
|
+
private handleTaskVerified(n: NotificationDetail): void {
|
|
227
|
+
this.triggerAgent(
|
|
228
|
+
`[Chorus] Task '${n.entityTitle}' has been verified and is now done (taskUuid: ${n.entityUuid}, projectUuid: ${n.projectUuid}). ` +
|
|
229
|
+
`Check if this unblocks other tasks: use chorus_get_unblocked_tasks with projectUuid "${n.projectUuid}" to find tasks that are now ready to start.`,
|
|
230
|
+
{ notificationUuid: n.uuid, action: "task_verified", entityUuid: n.entityUuid, projectUuid: n.projectUuid }
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
private handleTaskReopened(n: NotificationDetail): void {
|
|
235
|
+
const mentionGuidance = this.buildMentionGuidance(n, "task");
|
|
236
|
+
|
|
237
|
+
this.triggerAgent(
|
|
238
|
+
`[Chorus] Task '${n.entityTitle}' has been reopened and needs rework (taskUuid: ${n.entityUuid}, projectUuid: ${n.projectUuid}). ` +
|
|
239
|
+
`Use chorus_get_task to review the task and chorus_get_comments to see verification feedback, then fix the issues.\n${mentionGuidance}`,
|
|
240
|
+
{ notificationUuid: n.uuid, action: "task_reopened", entityUuid: n.entityUuid, projectUuid: n.projectUuid }
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
|
|
220
244
|
private handleElaborationAnswered(n: NotificationDetail): void {
|
|
221
245
|
const mentionGuidance = this.buildMentionGuidance(n, "idea");
|
|
222
246
|
|
|
@@ -260,7 +260,7 @@ export function registerCommonTools(api: any, mcpClient: ChorusMcpClient) {
|
|
|
260
260
|
|
|
261
261
|
api.registerTool({
|
|
262
262
|
name: "chorus_get_unblocked_tasks",
|
|
263
|
-
description: "Get tasks that are ready to start — status is open/assigned and all dependencies are resolved (done/
|
|
263
|
+
description: "Get tasks that are ready to start — status is open/assigned and all dependencies are resolved (done/closed). Note: to_verify is NOT considered resolved.",
|
|
264
264
|
parameters: {
|
|
265
265
|
type: "object",
|
|
266
266
|
properties: {
|
package/src/tools/dev-tools.ts
CHANGED
|
@@ -21,7 +21,7 @@ export function registerDevTools(api: any, mcpClient: ChorusMcpClient) {
|
|
|
21
21
|
|
|
22
22
|
api.registerTool({
|
|
23
23
|
name: "chorus_update_task",
|
|
24
|
-
description: "Update task status (only the assignee can operate)",
|
|
24
|
+
description: "Update task status (only the assignee can operate). Moving to in_progress requires all dependsOn tasks to be done or closed — otherwise the request is rejected with blocker details. Use chorus_get_unblocked_tasks to find tasks ready to start.",
|
|
25
25
|
parameters: {
|
|
26
26
|
type: "object",
|
|
27
27
|
properties: {
|
|
@@ -82,4 +82,64 @@ export function registerDevTools(api: any, mcpClient: ChorusMcpClient) {
|
|
|
82
82
|
return JSON.stringify(result, null, 2);
|
|
83
83
|
},
|
|
84
84
|
});
|
|
85
|
+
|
|
86
|
+
api.registerTool({
|
|
87
|
+
name: "chorus_report_criteria_self_check",
|
|
88
|
+
description: "Report self-check results on acceptance criteria for a task you're working on. For required criteria, keep working until all pass. Only mark optional criteria as failed if out of scope.",
|
|
89
|
+
parameters: {
|
|
90
|
+
type: "object",
|
|
91
|
+
properties: {
|
|
92
|
+
taskUuid: { type: "string", description: "Task UUID" },
|
|
93
|
+
criteria: {
|
|
94
|
+
type: "array",
|
|
95
|
+
description: "Array of { uuid, devStatus: 'passed'|'failed', devEvidence?: string }",
|
|
96
|
+
items: {
|
|
97
|
+
type: "object",
|
|
98
|
+
properties: {
|
|
99
|
+
uuid: { type: "string", description: "AcceptanceCriterion UUID" },
|
|
100
|
+
devStatus: { type: "string", description: "Self-check result: passed | failed" },
|
|
101
|
+
devEvidence: { type: "string", description: "Optional evidence/notes" },
|
|
102
|
+
},
|
|
103
|
+
required: ["uuid", "devStatus"],
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
required: ["taskUuid", "criteria"],
|
|
108
|
+
additionalProperties: false,
|
|
109
|
+
},
|
|
110
|
+
async execute(_id: string, { taskUuid, criteria }: { taskUuid: string; criteria: Array<{ uuid: string; devStatus: string; devEvidence?: string }> }) {
|
|
111
|
+
const result = await mcpClient.callTool("chorus_report_criteria_self_check", { taskUuid, criteria });
|
|
112
|
+
return JSON.stringify(result, null, 2);
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
api.registerTool({
|
|
117
|
+
name: "chorus_mark_acceptance_criteria",
|
|
118
|
+
description: "Mark acceptance criteria as passed or failed (admin verification). Blocked criteria prevent task from being verified (to_verify -> done).",
|
|
119
|
+
parameters: {
|
|
120
|
+
type: "object",
|
|
121
|
+
properties: {
|
|
122
|
+
taskUuid: { type: "string", description: "Task UUID" },
|
|
123
|
+
criteria: {
|
|
124
|
+
type: "array",
|
|
125
|
+
description: "Array of { uuid, status: 'passed'|'failed', evidence?: string }",
|
|
126
|
+
items: {
|
|
127
|
+
type: "object",
|
|
128
|
+
properties: {
|
|
129
|
+
uuid: { type: "string", description: "AcceptanceCriterion UUID" },
|
|
130
|
+
status: { type: "string", description: "Verification result: passed | failed" },
|
|
131
|
+
evidence: { type: "string", description: "Optional evidence/notes" },
|
|
132
|
+
},
|
|
133
|
+
required: ["uuid", "status"],
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
required: ["taskUuid", "criteria"],
|
|
138
|
+
additionalProperties: false,
|
|
139
|
+
},
|
|
140
|
+
async execute(_id: string, { taskUuid, criteria }: { taskUuid: string; criteria: Array<{ uuid: string; status: string; evidence?: string }> }) {
|
|
141
|
+
const result = await mcpClient.callTool("chorus_mark_acceptance_criteria", { taskUuid, criteria });
|
|
142
|
+
return JSON.stringify(result, null, 2);
|
|
143
|
+
},
|
|
144
|
+
});
|
|
85
145
|
}
|
package/src/tools/pm-tools.ts
CHANGED
|
@@ -108,7 +108,7 @@ export function registerPmTools(api: any, mcpClient: ChorusMcpClient) {
|
|
|
108
108
|
inputUuids: { type: "array", description: "Array of input UUIDs", items: { type: "string" } },
|
|
109
109
|
description: { type: "string", description: "Proposal description" },
|
|
110
110
|
documentDrafts: { type: "array", description: "Array of { type, title, content }", items: { type: "object" } },
|
|
111
|
-
taskDrafts: { type: "array", description: "Array of { title, description?, priority?, storyPoints?,
|
|
111
|
+
taskDrafts: { type: "array", description: "Array of { title, description?, priority?, storyPoints?, acceptanceCriteriaItems?, dependsOnDraftUuids? }", items: { type: "object" } },
|
|
112
112
|
},
|
|
113
113
|
required: ["projectUuid", "title", "inputType", "inputUuids"],
|
|
114
114
|
additionalProperties: false,
|
|
@@ -158,20 +158,20 @@ export function registerPmTools(api: any, mcpClient: ChorusMcpClient) {
|
|
|
158
158
|
description: { type: "string", description: "Task description" },
|
|
159
159
|
priority: { type: "string", description: 'Priority: "low", "medium", or "high"' },
|
|
160
160
|
storyPoints: { type: "number", description: "Effort estimate in agent hours" },
|
|
161
|
-
|
|
161
|
+
acceptanceCriteriaItems: { type: "array", description: "Structured acceptance criteria: [{ description, required? }]", items: { type: "object", properties: { description: { type: "string" }, required: { type: "boolean" } }, required: ["description"] } },
|
|
162
162
|
dependsOnDraftUuids: { type: "array", description: "Dependent task draft UUIDs", items: { type: "string" } },
|
|
163
163
|
},
|
|
164
164
|
required: ["proposalUuid", "title"],
|
|
165
165
|
additionalProperties: false,
|
|
166
166
|
},
|
|
167
167
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
168
|
-
async execute(_id: string, { proposalUuid, title, description, priority, storyPoints,
|
|
168
|
+
async execute(_id: string, { proposalUuid, title, description, priority, storyPoints, acceptanceCriteriaItems, dependsOnDraftUuids }: any) {
|
|
169
169
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
170
170
|
const args: Record<string, any> = { proposalUuid, title };
|
|
171
171
|
if (description !== undefined) args.description = description;
|
|
172
172
|
if (priority !== undefined) args.priority = priority;
|
|
173
173
|
if (storyPoints !== undefined) args.storyPoints = storyPoints;
|
|
174
|
-
if (
|
|
174
|
+
if (acceptanceCriteriaItems !== undefined) args.acceptanceCriteriaItems = acceptanceCriteriaItems;
|
|
175
175
|
if (dependsOnDraftUuids !== undefined) args.dependsOnDraftUuids = dependsOnDraftUuids;
|
|
176
176
|
const result = await mcpClient.callTool("chorus_pm_add_task_draft", args);
|
|
177
177
|
return JSON.stringify(result, null, 2);
|
|
@@ -237,21 +237,21 @@ export function registerPmTools(api: any, mcpClient: ChorusMcpClient) {
|
|
|
237
237
|
description: { type: "string", description: "New task description" },
|
|
238
238
|
priority: { type: "string", description: 'Priority: "low", "medium", or "high"' },
|
|
239
239
|
storyPoints: { type: "number", description: "Effort estimate in agent hours" },
|
|
240
|
-
|
|
240
|
+
acceptanceCriteriaItems: { type: "array", description: "Structured acceptance criteria: [{ description, required? }]", items: { type: "object", properties: { description: { type: "string" }, required: { type: "boolean" } }, required: ["description"] } },
|
|
241
241
|
dependsOnDraftUuids: { type: "array", description: "Task draft UUIDs this task depends on (sets execution order)", items: { type: "string" } },
|
|
242
242
|
},
|
|
243
243
|
required: ["proposalUuid", "draftUuid"],
|
|
244
244
|
additionalProperties: false,
|
|
245
245
|
},
|
|
246
246
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
247
|
-
async execute(_id: string, { proposalUuid, draftUuid, title, description, priority, storyPoints,
|
|
247
|
+
async execute(_id: string, { proposalUuid, draftUuid, title, description, priority, storyPoints, acceptanceCriteriaItems, dependsOnDraftUuids }: any) {
|
|
248
248
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
249
249
|
const args: Record<string, any> = { proposalUuid, draftUuid };
|
|
250
250
|
if (title !== undefined) args.title = title;
|
|
251
251
|
if (description !== undefined) args.description = description;
|
|
252
252
|
if (priority !== undefined) args.priority = priority;
|
|
253
253
|
if (storyPoints !== undefined) args.storyPoints = storyPoints;
|
|
254
|
-
if (
|
|
254
|
+
if (acceptanceCriteriaItems !== undefined) args.acceptanceCriteriaItems = acceptanceCriteriaItems;
|
|
255
255
|
if (dependsOnDraftUuids !== undefined) args.dependsOnDraftUuids = dependsOnDraftUuids;
|
|
256
256
|
const result = await mcpClient.callTool("chorus_pm_update_task_draft", args);
|
|
257
257
|
return JSON.stringify(result, null, 2);
|