musubi-sdd 3.0.1 → 3.5.1
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/bin/musubi-change.js +623 -10
- package/bin/musubi-orchestrate.js +456 -0
- package/bin/musubi-trace.js +393 -0
- package/package.json +3 -2
- package/src/analyzers/impact-analyzer.js +682 -0
- package/src/integrations/cicd.js +782 -0
- package/src/integrations/documentation.js +740 -0
- package/src/integrations/examples.js +789 -0
- package/src/integrations/index.js +23 -0
- package/src/integrations/platforms.js +929 -0
- package/src/managers/delta-spec.js +484 -0
- package/src/monitoring/incident-manager.js +890 -0
- package/src/monitoring/index.js +633 -0
- package/src/monitoring/observability.js +938 -0
- package/src/monitoring/release-manager.js +622 -0
- package/src/orchestration/index.js +168 -0
- package/src/orchestration/orchestration-engine.js +409 -0
- package/src/orchestration/pattern-registry.js +319 -0
- package/src/orchestration/patterns/auto.js +386 -0
- package/src/orchestration/patterns/group-chat.js +395 -0
- package/src/orchestration/patterns/human-in-loop.js +506 -0
- package/src/orchestration/patterns/nested.js +322 -0
- package/src/orchestration/patterns/sequential.js +278 -0
- package/src/orchestration/patterns/swarm.js +395 -0
- package/src/orchestration/workflow-orchestrator.js +738 -0
- package/src/reporters/coverage-report.js +452 -0
- package/src/reporters/traceability-matrix-report.js +684 -0
- package/src/steering/advanced-validation.js +812 -0
- package/src/steering/auto-updater.js +670 -0
- package/src/steering/index.js +119 -0
- package/src/steering/quality-metrics.js +650 -0
- package/src/steering/template-constraints.js +789 -0
- package/src/templates/agents/claude-code/skills/agent-assistant/SKILL.md +22 -0
- package/src/templates/agents/claude-code/skills/issue-resolver/SKILL.md +21 -0
- package/src/templates/agents/claude-code/skills/orchestrator/SKILL.md +90 -28
- package/src/templates/agents/claude-code/skills/project-manager/SKILL.md +32 -0
- package/src/templates/agents/claude-code/skills/site-reliability-engineer/SKILL.md +27 -0
- package/src/templates/agents/claude-code/skills/steering/SKILL.md +30 -0
- package/src/templates/agents/claude-code/skills/test-engineer/SKILL.md +21 -0
- package/src/templates/agents/claude-code/skills/ui-ux-designer/SKILL.md +27 -0
- package/src/templates/agents/codex/AGENTS.md +36 -1
- package/src/templates/agents/cursor/AGENTS.md +36 -1
- package/src/templates/agents/gemini-cli/GEMINI.md +36 -1
- package/src/templates/agents/github-copilot/AGENTS.md +65 -1
- package/src/templates/agents/qwen-code/QWEN.md +36 -1
- package/src/templates/agents/windsurf/AGENTS.md +36 -1
- package/src/templates/shared/delta-spec-template.md +246 -0
- package/src/validators/delta-format.js +474 -0
- package/src/validators/traceability-validator.js +561 -0
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GroupChatPattern - Multi-skill collaborative discussion pattern
|
|
3
|
+
*
|
|
4
|
+
* Enables multiple skills to collaborate on a task through
|
|
5
|
+
* iterative discussion and consensus building.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { BasePattern } = require('../pattern-registry');
|
|
9
|
+
const { PatternType, ExecutionContext, ExecutionStatus } = require('../orchestration-engine');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Discussion mode
|
|
13
|
+
*/
|
|
14
|
+
const DiscussionMode = {
|
|
15
|
+
ROUND_ROBIN: 'round-robin', // Each skill speaks in turn
|
|
16
|
+
OPEN_FLOOR: 'open-floor', // Skills speak based on relevance
|
|
17
|
+
MODERATED: 'moderated' // Moderator skill controls discussion
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Consensus type
|
|
22
|
+
*/
|
|
23
|
+
const ConsensusType = {
|
|
24
|
+
UNANIMOUS: 'unanimous', // All must agree
|
|
25
|
+
MAJORITY: 'majority', // 50%+ must agree
|
|
26
|
+
FIRST_AGREEMENT: 'first' // First agreement wins
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* GroupChatPattern - Multi-skill collaboration
|
|
31
|
+
*/
|
|
32
|
+
class GroupChatPattern extends BasePattern {
|
|
33
|
+
constructor(options = {}) {
|
|
34
|
+
super({
|
|
35
|
+
name: PatternType.GROUP_CHAT,
|
|
36
|
+
type: PatternType.GROUP_CHAT,
|
|
37
|
+
description: 'Enable multi-skill collaborative discussion and consensus',
|
|
38
|
+
version: '1.0.0',
|
|
39
|
+
tags: ['collaboration', 'discussion', 'consensus', 'multi-agent'],
|
|
40
|
+
useCases: [
|
|
41
|
+
'Design reviews',
|
|
42
|
+
'Code reviews',
|
|
43
|
+
'Decision making',
|
|
44
|
+
'Brainstorming'
|
|
45
|
+
],
|
|
46
|
+
complexity: 'high',
|
|
47
|
+
supportsParallel: false,
|
|
48
|
+
requiresHuman: false
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
this.options = {
|
|
52
|
+
mode: options.mode || DiscussionMode.ROUND_ROBIN,
|
|
53
|
+
consensusType: options.consensusType || ConsensusType.MAJORITY,
|
|
54
|
+
maxRounds: options.maxRounds || 5,
|
|
55
|
+
moderator: options.moderator || null,
|
|
56
|
+
convergenceThreshold: options.convergenceThreshold || 0.8,
|
|
57
|
+
...options
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Validate the execution context
|
|
63
|
+
* @param {ExecutionContext} context - Execution context
|
|
64
|
+
* @param {OrchestrationEngine} engine - Orchestration engine
|
|
65
|
+
* @returns {object} Validation result
|
|
66
|
+
*/
|
|
67
|
+
validate(context, engine) {
|
|
68
|
+
const errors = [];
|
|
69
|
+
const input = context.input;
|
|
70
|
+
|
|
71
|
+
// Check for participants
|
|
72
|
+
if (!input.participants || !Array.isArray(input.participants)) {
|
|
73
|
+
errors.push('GroupChat pattern requires input.participants array');
|
|
74
|
+
} else if (input.participants.length < 2) {
|
|
75
|
+
errors.push('GroupChat pattern requires at least 2 participants');
|
|
76
|
+
} else {
|
|
77
|
+
// Validate each participant exists
|
|
78
|
+
for (const skillName of input.participants) {
|
|
79
|
+
if (!engine.getSkill(skillName)) {
|
|
80
|
+
errors.push(`Unknown participant skill: ${skillName}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Check topic
|
|
86
|
+
if (!input.topic) {
|
|
87
|
+
errors.push('GroupChat pattern requires input.topic');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Check moderator if mode is moderated
|
|
91
|
+
if (this.options.mode === DiscussionMode.MODERATED) {
|
|
92
|
+
const moderator = this.options.moderator || input.moderator;
|
|
93
|
+
if (!moderator) {
|
|
94
|
+
errors.push('Moderated mode requires a moderator skill');
|
|
95
|
+
} else if (!engine.getSkill(moderator)) {
|
|
96
|
+
errors.push(`Unknown moderator skill: ${moderator}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
valid: errors.length === 0,
|
|
102
|
+
errors
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Execute group chat pattern
|
|
108
|
+
* @param {ExecutionContext} context - Execution context
|
|
109
|
+
* @param {OrchestrationEngine} engine - Orchestration engine
|
|
110
|
+
* @returns {Promise<object>} Execution result
|
|
111
|
+
*/
|
|
112
|
+
async execute(context, engine) {
|
|
113
|
+
const validation = this.validate(context, engine);
|
|
114
|
+
if (!validation.valid) {
|
|
115
|
+
throw new Error(`Validation failed: ${validation.errors.join(', ')}`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const { participants, topic, initialContext = {} } = context.input;
|
|
119
|
+
const transcript = [];
|
|
120
|
+
let consensusReached = false;
|
|
121
|
+
let finalDecision = null;
|
|
122
|
+
let round = 0;
|
|
123
|
+
|
|
124
|
+
engine.emit('groupChatStarted', {
|
|
125
|
+
context,
|
|
126
|
+
participants,
|
|
127
|
+
topic,
|
|
128
|
+
mode: this.options.mode
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
while (round < this.options.maxRounds && !consensusReached) {
|
|
133
|
+
round++;
|
|
134
|
+
|
|
135
|
+
engine.emit('groupChatRoundStarted', {
|
|
136
|
+
context,
|
|
137
|
+
round,
|
|
138
|
+
maxRounds: this.options.maxRounds
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
const roundResponses = await this._executeRound(
|
|
142
|
+
participants,
|
|
143
|
+
topic,
|
|
144
|
+
transcript,
|
|
145
|
+
initialContext,
|
|
146
|
+
context,
|
|
147
|
+
engine,
|
|
148
|
+
round
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
transcript.push({
|
|
152
|
+
round,
|
|
153
|
+
responses: roundResponses
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// Check for consensus
|
|
157
|
+
const consensusResult = this._checkConsensus(roundResponses);
|
|
158
|
+
consensusReached = consensusResult.reached;
|
|
159
|
+
|
|
160
|
+
if (consensusReached) {
|
|
161
|
+
finalDecision = consensusResult.decision;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
engine.emit('groupChatRoundCompleted', {
|
|
165
|
+
context,
|
|
166
|
+
round,
|
|
167
|
+
responses: roundResponses,
|
|
168
|
+
consensusReached
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const summary = this._createSummary(transcript, consensusReached, round);
|
|
173
|
+
|
|
174
|
+
engine.emit('groupChatCompleted', {
|
|
175
|
+
context,
|
|
176
|
+
transcript,
|
|
177
|
+
consensusReached,
|
|
178
|
+
finalDecision,
|
|
179
|
+
summary
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
return {
|
|
183
|
+
transcript,
|
|
184
|
+
rounds: round,
|
|
185
|
+
consensusReached,
|
|
186
|
+
finalDecision,
|
|
187
|
+
summary
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
} catch (error) {
|
|
191
|
+
engine.emit('groupChatFailed', {
|
|
192
|
+
context,
|
|
193
|
+
transcript,
|
|
194
|
+
round,
|
|
195
|
+
error
|
|
196
|
+
});
|
|
197
|
+
throw error;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Execute a single round of discussion
|
|
203
|
+
* @private
|
|
204
|
+
*/
|
|
205
|
+
async _executeRound(participants, topic, transcript, initialContext, parentContext, engine, round) {
|
|
206
|
+
const responses = [];
|
|
207
|
+
const discussionContext = {
|
|
208
|
+
topic,
|
|
209
|
+
round,
|
|
210
|
+
previousRounds: transcript,
|
|
211
|
+
...initialContext
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
for (const participant of participants) {
|
|
215
|
+
const stepContext = new ExecutionContext({
|
|
216
|
+
task: `GroupChat round ${round}: ${participant}`,
|
|
217
|
+
skill: participant,
|
|
218
|
+
input: {
|
|
219
|
+
...discussionContext,
|
|
220
|
+
previousResponses: responses,
|
|
221
|
+
role: 'participant'
|
|
222
|
+
},
|
|
223
|
+
parentId: parentContext.id,
|
|
224
|
+
metadata: {
|
|
225
|
+
pattern: PatternType.GROUP_CHAT,
|
|
226
|
+
round,
|
|
227
|
+
participant
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
parentContext.children.push(stepContext);
|
|
232
|
+
|
|
233
|
+
try {
|
|
234
|
+
stepContext.start();
|
|
235
|
+
|
|
236
|
+
const response = await engine.executeSkill(
|
|
237
|
+
participant,
|
|
238
|
+
stepContext.input,
|
|
239
|
+
parentContext
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
stepContext.complete(response);
|
|
243
|
+
|
|
244
|
+
responses.push({
|
|
245
|
+
participant,
|
|
246
|
+
response,
|
|
247
|
+
status: ExecutionStatus.COMPLETED
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
engine.emit('groupChatResponse', {
|
|
251
|
+
participant,
|
|
252
|
+
round,
|
|
253
|
+
response
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
} catch (error) {
|
|
257
|
+
stepContext.fail(error);
|
|
258
|
+
|
|
259
|
+
responses.push({
|
|
260
|
+
participant,
|
|
261
|
+
error: error.message,
|
|
262
|
+
status: ExecutionStatus.FAILED
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
return responses;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Check for consensus among responses
|
|
272
|
+
* @private
|
|
273
|
+
*/
|
|
274
|
+
_checkConsensus(responses) {
|
|
275
|
+
const validResponses = responses.filter(r =>
|
|
276
|
+
r.status === ExecutionStatus.COMPLETED
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
if (validResponses.length === 0) {
|
|
280
|
+
return { reached: false, decision: null };
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Extract decisions from responses
|
|
284
|
+
const decisions = validResponses.map(r => {
|
|
285
|
+
if (r.response && typeof r.response === 'object') {
|
|
286
|
+
return r.response.decision || r.response.recommendation || r.response.answer;
|
|
287
|
+
}
|
|
288
|
+
return r.response;
|
|
289
|
+
}).filter(d => d !== undefined && d !== null);
|
|
290
|
+
|
|
291
|
+
if (decisions.length === 0) {
|
|
292
|
+
return { reached: false, decision: null };
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Count votes for each decision
|
|
296
|
+
const votes = {};
|
|
297
|
+
for (const decision of decisions) {
|
|
298
|
+
const key = typeof decision === 'object'
|
|
299
|
+
? JSON.stringify(decision)
|
|
300
|
+
: String(decision);
|
|
301
|
+
votes[key] = (votes[key] || 0) + 1;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Find most common decision
|
|
305
|
+
let maxVotes = 0;
|
|
306
|
+
let winningDecision = null;
|
|
307
|
+
for (const [decision, count] of Object.entries(votes)) {
|
|
308
|
+
if (count > maxVotes) {
|
|
309
|
+
maxVotes = count;
|
|
310
|
+
try {
|
|
311
|
+
winningDecision = JSON.parse(decision);
|
|
312
|
+
} catch {
|
|
313
|
+
winningDecision = decision;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Check consensus based on type
|
|
319
|
+
const total = validResponses.length;
|
|
320
|
+
|
|
321
|
+
switch (this.options.consensusType) {
|
|
322
|
+
case ConsensusType.UNANIMOUS:
|
|
323
|
+
return {
|
|
324
|
+
reached: maxVotes === total,
|
|
325
|
+
decision: maxVotes === total ? winningDecision : null
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
case ConsensusType.MAJORITY:
|
|
329
|
+
return {
|
|
330
|
+
reached: maxVotes > total / 2,
|
|
331
|
+
decision: maxVotes > total / 2 ? winningDecision : null
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
case ConsensusType.FIRST_AGREEMENT:
|
|
335
|
+
return {
|
|
336
|
+
reached: maxVotes >= 2,
|
|
337
|
+
decision: maxVotes >= 2 ? winningDecision : null
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
default:
|
|
341
|
+
return {
|
|
342
|
+
reached: maxVotes >= total * this.options.convergenceThreshold,
|
|
343
|
+
decision: winningDecision
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Create execution summary
|
|
350
|
+
* @private
|
|
351
|
+
*/
|
|
352
|
+
_createSummary(transcript, consensusReached, totalRounds) {
|
|
353
|
+
let totalResponses = 0;
|
|
354
|
+
let successfulResponses = 0;
|
|
355
|
+
let failedResponses = 0;
|
|
356
|
+
|
|
357
|
+
for (const round of transcript) {
|
|
358
|
+
for (const response of round.responses) {
|
|
359
|
+
totalResponses++;
|
|
360
|
+
if (response.status === ExecutionStatus.COMPLETED) {
|
|
361
|
+
successfulResponses++;
|
|
362
|
+
} else {
|
|
363
|
+
failedResponses++;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
return {
|
|
369
|
+
totalRounds,
|
|
370
|
+
totalResponses,
|
|
371
|
+
successfulResponses,
|
|
372
|
+
failedResponses,
|
|
373
|
+
consensusReached,
|
|
374
|
+
successRate: totalResponses > 0
|
|
375
|
+
? (successfulResponses / totalResponses * 100).toFixed(1) + '%'
|
|
376
|
+
: '0%'
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Create a group chat pattern with custom options
|
|
383
|
+
* @param {object} options - Pattern options
|
|
384
|
+
* @returns {GroupChatPattern} GroupChat pattern instance
|
|
385
|
+
*/
|
|
386
|
+
function createGroupChatPattern(options = {}) {
|
|
387
|
+
return new GroupChatPattern(options);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
module.exports = {
|
|
391
|
+
GroupChatPattern,
|
|
392
|
+
DiscussionMode,
|
|
393
|
+
ConsensusType,
|
|
394
|
+
createGroupChatPattern
|
|
395
|
+
};
|