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.
Files changed (49) hide show
  1. package/bin/musubi-change.js +623 -10
  2. package/bin/musubi-orchestrate.js +456 -0
  3. package/bin/musubi-trace.js +393 -0
  4. package/package.json +3 -2
  5. package/src/analyzers/impact-analyzer.js +682 -0
  6. package/src/integrations/cicd.js +782 -0
  7. package/src/integrations/documentation.js +740 -0
  8. package/src/integrations/examples.js +789 -0
  9. package/src/integrations/index.js +23 -0
  10. package/src/integrations/platforms.js +929 -0
  11. package/src/managers/delta-spec.js +484 -0
  12. package/src/monitoring/incident-manager.js +890 -0
  13. package/src/monitoring/index.js +633 -0
  14. package/src/monitoring/observability.js +938 -0
  15. package/src/monitoring/release-manager.js +622 -0
  16. package/src/orchestration/index.js +168 -0
  17. package/src/orchestration/orchestration-engine.js +409 -0
  18. package/src/orchestration/pattern-registry.js +319 -0
  19. package/src/orchestration/patterns/auto.js +386 -0
  20. package/src/orchestration/patterns/group-chat.js +395 -0
  21. package/src/orchestration/patterns/human-in-loop.js +506 -0
  22. package/src/orchestration/patterns/nested.js +322 -0
  23. package/src/orchestration/patterns/sequential.js +278 -0
  24. package/src/orchestration/patterns/swarm.js +395 -0
  25. package/src/orchestration/workflow-orchestrator.js +738 -0
  26. package/src/reporters/coverage-report.js +452 -0
  27. package/src/reporters/traceability-matrix-report.js +684 -0
  28. package/src/steering/advanced-validation.js +812 -0
  29. package/src/steering/auto-updater.js +670 -0
  30. package/src/steering/index.js +119 -0
  31. package/src/steering/quality-metrics.js +650 -0
  32. package/src/steering/template-constraints.js +789 -0
  33. package/src/templates/agents/claude-code/skills/agent-assistant/SKILL.md +22 -0
  34. package/src/templates/agents/claude-code/skills/issue-resolver/SKILL.md +21 -0
  35. package/src/templates/agents/claude-code/skills/orchestrator/SKILL.md +90 -28
  36. package/src/templates/agents/claude-code/skills/project-manager/SKILL.md +32 -0
  37. package/src/templates/agents/claude-code/skills/site-reliability-engineer/SKILL.md +27 -0
  38. package/src/templates/agents/claude-code/skills/steering/SKILL.md +30 -0
  39. package/src/templates/agents/claude-code/skills/test-engineer/SKILL.md +21 -0
  40. package/src/templates/agents/claude-code/skills/ui-ux-designer/SKILL.md +27 -0
  41. package/src/templates/agents/codex/AGENTS.md +36 -1
  42. package/src/templates/agents/cursor/AGENTS.md +36 -1
  43. package/src/templates/agents/gemini-cli/GEMINI.md +36 -1
  44. package/src/templates/agents/github-copilot/AGENTS.md +65 -1
  45. package/src/templates/agents/qwen-code/QWEN.md +36 -1
  46. package/src/templates/agents/windsurf/AGENTS.md +36 -1
  47. package/src/templates/shared/delta-spec-template.md +246 -0
  48. package/src/validators/delta-format.js +474 -0
  49. 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
+ };