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,456 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * MUSUBI Orchestration CLI
5
+ *
6
+ * Multi-skill orchestration with ag2-inspired patterns
7
+ *
8
+ * Usage:
9
+ * musubi-orchestrate run <pattern> --skills <skills...> # Execute pattern with skills
10
+ * musubi-orchestrate auto <task> # Auto-select and execute skill
11
+ * musubi-orchestrate sequential --skills <skills...> # Execute skills sequentially
12
+ * musubi-orchestrate list-patterns # List available patterns
13
+ * musubi-orchestrate list-skills # List available skills
14
+ * musubi-orchestrate status # Show orchestration status
15
+ */
16
+
17
+ const { Command } = require('commander');
18
+ const chalk = require('chalk');
19
+ const path = require('path');
20
+ const fs = require('fs-extra');
21
+
22
+ const {
23
+ createOrchestrationEngine,
24
+ PatternType,
25
+ ExecutionStatus,
26
+ Priority
27
+ } = require('../src/orchestration');
28
+
29
+ const program = new Command();
30
+
31
+ program
32
+ .name('musubi-orchestrate')
33
+ .description('MUSUBI Orchestration - Multi-skill workflow orchestration')
34
+ .version('1.0.0');
35
+
36
+ /**
37
+ * Load skills from templates
38
+ */
39
+ async function loadSkills(projectPath) {
40
+ const skills = new Map();
41
+ const skillsPath = path.join(projectPath, 'src', 'templates', 'skills');
42
+
43
+ if (await fs.pathExists(skillsPath)) {
44
+ const skillDirs = await fs.readdir(skillsPath);
45
+
46
+ for (const skillDir of skillDirs) {
47
+ const skillPath = path.join(skillsPath, skillDir);
48
+ const stat = await fs.stat(skillPath);
49
+
50
+ if (stat.isDirectory()) {
51
+ const metaPath = path.join(skillPath, 'skill.json');
52
+
53
+ if (await fs.pathExists(metaPath)) {
54
+ try {
55
+ const meta = await fs.readJson(metaPath);
56
+ skills.set(skillDir, {
57
+ name: skillDir,
58
+ ...meta,
59
+ execute: async (input) => {
60
+ // Placeholder for actual skill execution
61
+ return { skill: skillDir, input, executed: true };
62
+ }
63
+ });
64
+ } catch (e) {
65
+ // Skip invalid skills
66
+ }
67
+ } else {
68
+ // Create minimal skill entry
69
+ skills.set(skillDir, {
70
+ name: skillDir,
71
+ description: `${skillDir} skill`,
72
+ keywords: [skillDir],
73
+ execute: async (input) => {
74
+ return { skill: skillDir, input, executed: true };
75
+ }
76
+ });
77
+ }
78
+ }
79
+ }
80
+ }
81
+
82
+ // Add built-in mock skills for demonstration
83
+ if (skills.size === 0) {
84
+ const mockSkills = [
85
+ { name: 'requirements-analyst', keywords: ['requirement', 'ears', 'specification'], categories: ['requirements'] },
86
+ { name: 'system-architect', keywords: ['architecture', 'design', 'c4'], categories: ['design'] },
87
+ { name: 'task-decomposer', keywords: ['task', 'breakdown', 'decompose'], categories: ['implementation'] },
88
+ { name: 'code-generator', keywords: ['code', 'implement', 'generate'], categories: ['implementation'] },
89
+ { name: 'test-engineer', keywords: ['test', 'testing', 'qa'], categories: ['testing'] },
90
+ { name: 'documentation-writer', keywords: ['document', 'readme', 'guide'], categories: ['documentation'] },
91
+ { name: 'security-analyst', keywords: ['security', 'vulnerability', 'audit'], categories: ['security'] },
92
+ { name: 'performance-engineer', keywords: ['performance', 'optimize', 'benchmark'], categories: ['performance'] }
93
+ ];
94
+
95
+ for (const skill of mockSkills) {
96
+ skills.set(skill.name, {
97
+ ...skill,
98
+ description: `${skill.name} skill`,
99
+ execute: async (input) => {
100
+ return { skill: skill.name, input, executed: true, mock: true };
101
+ }
102
+ });
103
+ }
104
+ }
105
+
106
+ return skills;
107
+ }
108
+
109
+ /**
110
+ * Create configured engine
111
+ */
112
+ async function createEngine(projectPath) {
113
+ const engine = createOrchestrationEngine({
114
+ maxConcurrent: 5,
115
+ timeout: 300000
116
+ });
117
+
118
+ // Load and register skills
119
+ const skills = await loadSkills(projectPath);
120
+ for (const [name, skill] of skills) {
121
+ engine.registerSkill(name, skill);
122
+ }
123
+
124
+ return engine;
125
+ }
126
+
127
+ /**
128
+ * Format execution result
129
+ */
130
+ function formatResult(result, format = 'text') {
131
+ if (format === 'json') {
132
+ return JSON.stringify(result, null, 2);
133
+ }
134
+
135
+ let output = '';
136
+
137
+ if (result.selectedSkill) {
138
+ output += chalk.bold(`Selected Skill: `) + chalk.cyan(result.selectedSkill) + '\n';
139
+ output += chalk.bold(`Confidence: `) + formatConfidence(result.confidence) + '\n';
140
+ }
141
+
142
+ if (result.results) {
143
+ output += chalk.bold('\nExecution Results:\n');
144
+ for (const r of result.results) {
145
+ const status = r.status === ExecutionStatus.COMPLETED
146
+ ? chalk.green('āœ“')
147
+ : chalk.red('āœ—');
148
+ const step = r.step ? `Step ${r.step}: ` : '';
149
+ output += ` ${status} ${step}${chalk.cyan(r.skill)}`;
150
+ if (r.error) {
151
+ output += ` - ${chalk.red(r.error)}`;
152
+ }
153
+ output += '\n';
154
+ }
155
+ }
156
+
157
+ if (result.summary) {
158
+ output += chalk.bold('\nSummary:\n');
159
+ output += ` Total Steps: ${result.summary.totalSteps}\n`;
160
+ output += ` Completed: ${chalk.green(result.summary.completed)}\n`;
161
+ output += ` Failed: ${chalk.red(result.summary.failed)}\n`;
162
+ output += ` Success Rate: ${result.summary.successRate}\n`;
163
+ }
164
+
165
+ return output;
166
+ }
167
+
168
+ /**
169
+ * Format confidence level
170
+ */
171
+ function formatConfidence(confidence) {
172
+ if (confidence >= 0.8) return chalk.green(`${(confidence * 100).toFixed(0)}% (High)`);
173
+ if (confidence >= 0.5) return chalk.yellow(`${(confidence * 100).toFixed(0)}% (Medium)`);
174
+ return chalk.red(`${(confidence * 100).toFixed(0)}% (Low)`);
175
+ }
176
+
177
+ // Run pattern command
178
+ program
179
+ .command('run <pattern>')
180
+ .description('Execute an orchestration pattern')
181
+ .option('-s, --skills <skills...>', 'Skills to execute')
182
+ .option('-t, --task <task>', 'Task description')
183
+ .option('-i, --input <json>', 'Input data as JSON')
184
+ .option('-f, --format <type>', 'Output format (text|json)', 'text')
185
+ .action(async (pattern, options) => {
186
+ try {
187
+ console.log(chalk.bold(`\nšŸŽ­ Running ${pattern} pattern\n`));
188
+
189
+ const engine = await createEngine(process.cwd());
190
+
191
+ const input = options.input ? JSON.parse(options.input) : {};
192
+ if (options.skills) {
193
+ input.skills = options.skills;
194
+ }
195
+
196
+ const context = await engine.execute(pattern, {
197
+ task: options.task || `Execute ${pattern} pattern`,
198
+ input
199
+ });
200
+
201
+ if (context.status === ExecutionStatus.COMPLETED) {
202
+ console.log(chalk.green('āœ“ Pattern execution completed\n'));
203
+ console.log(formatResult(context.output, options.format));
204
+ } else {
205
+ console.log(chalk.red(`āœ— Pattern execution failed: ${context.error}\n`));
206
+ process.exit(1);
207
+ }
208
+
209
+ } catch (error) {
210
+ console.error(chalk.red(`\nāœ— Error: ${error.message}\n`));
211
+ if (process.env.DEBUG) {
212
+ console.error(error.stack);
213
+ }
214
+ process.exit(1);
215
+ }
216
+ });
217
+
218
+ // Auto pattern command
219
+ program
220
+ .command('auto <task>')
221
+ .description('Automatically select and execute the best skill for a task')
222
+ .option('-i, --input <json>', 'Input data as JSON')
223
+ .option('-f, --format <type>', 'Output format (text|json)', 'text')
224
+ .option('--multi', 'Execute multiple matching skills')
225
+ .action(async (task, options) => {
226
+ try {
227
+ console.log(chalk.bold('\nšŸ¤– Auto Pattern - Intelligent Skill Selection\n'));
228
+ console.log(chalk.dim(`Task: ${task}\n`));
229
+
230
+ const engine = await createEngine(process.cwd());
231
+
232
+ const input = options.input ? JSON.parse(options.input) : {};
233
+ input.task = task;
234
+
235
+ // Update auto pattern config if multi mode
236
+ if (options.multi) {
237
+ const autoPattern = engine.getPattern(PatternType.AUTO);
238
+ if (autoPattern) {
239
+ autoPattern.options.multiMatch = true;
240
+ }
241
+ }
242
+
243
+ const context = await engine.execute(PatternType.AUTO, {
244
+ task,
245
+ input
246
+ });
247
+
248
+ if (context.status === ExecutionStatus.COMPLETED) {
249
+ console.log(chalk.green('āœ“ Auto execution completed\n'));
250
+ console.log(formatResult(context.output, options.format));
251
+ } else {
252
+ console.log(chalk.red(`āœ— Auto execution failed: ${context.error}\n`));
253
+ process.exit(1);
254
+ }
255
+
256
+ } catch (error) {
257
+ console.error(chalk.red(`\nāœ— Error: ${error.message}\n`));
258
+ if (process.env.DEBUG) {
259
+ console.error(error.stack);
260
+ }
261
+ process.exit(1);
262
+ }
263
+ });
264
+
265
+ // Sequential pattern command
266
+ program
267
+ .command('sequential')
268
+ .description('Execute skills in sequence')
269
+ .requiredOption('-s, --skills <skills...>', 'Skills to execute in order')
270
+ .option('-i, --input <json>', 'Initial input data as JSON')
271
+ .option('-f, --format <type>', 'Output format (text|json)', 'text')
272
+ .option('--continue-on-error', 'Continue execution on error')
273
+ .action(async (options) => {
274
+ try {
275
+ console.log(chalk.bold('\nšŸ”— Sequential Pattern - Step-by-Step Execution\n'));
276
+ console.log(chalk.dim(`Skills: ${options.skills.join(' → ')}\n`));
277
+
278
+ const engine = await createEngine(process.cwd());
279
+
280
+ const initialInput = options.input ? JSON.parse(options.input) : {};
281
+
282
+ const context = await engine.execute(PatternType.SEQUENTIAL, {
283
+ task: `Sequential execution of ${options.skills.length} skills`,
284
+ input: {
285
+ skills: options.skills,
286
+ initialInput
287
+ }
288
+ });
289
+
290
+ if (context.status === ExecutionStatus.COMPLETED) {
291
+ console.log(chalk.green('\nāœ“ Sequential execution completed\n'));
292
+ console.log(formatResult(context.output, options.format));
293
+ } else {
294
+ console.log(chalk.red(`\nāœ— Sequential execution failed: ${context.error}\n`));
295
+ process.exit(1);
296
+ }
297
+
298
+ } catch (error) {
299
+ console.error(chalk.red(`\nāœ— Error: ${error.message}\n`));
300
+ if (process.env.DEBUG) {
301
+ console.error(error.stack);
302
+ }
303
+ process.exit(1);
304
+ }
305
+ });
306
+
307
+ // List patterns command
308
+ program
309
+ .command('list-patterns')
310
+ .description('List available orchestration patterns')
311
+ .option('-f, --format <type>', 'Output format (text|json)', 'text')
312
+ .action(async (options) => {
313
+ try {
314
+ console.log(chalk.bold('\nšŸŽ­ Available Orchestration Patterns\n'));
315
+
316
+ const engine = await createEngine(process.cwd());
317
+ const patterns = engine.listPatterns();
318
+
319
+ if (options.format === 'json') {
320
+ const patternData = patterns.map(name => {
321
+ const pattern = engine.getPattern(name);
322
+ return {
323
+ name,
324
+ metadata: pattern.metadata || { name }
325
+ };
326
+ });
327
+ console.log(JSON.stringify(patternData, null, 2));
328
+ } else {
329
+ if (patterns.length === 0) {
330
+ console.log(chalk.yellow('No patterns registered'));
331
+ } else {
332
+ for (const name of patterns) {
333
+ const pattern = engine.getPattern(name);
334
+ const meta = pattern.metadata || {};
335
+ console.log(chalk.cyan(` ${name}`));
336
+ if (meta.description) {
337
+ console.log(chalk.dim(` ${meta.description}`));
338
+ }
339
+ }
340
+ }
341
+ }
342
+
343
+ console.log('');
344
+
345
+ } catch (error) {
346
+ console.error(chalk.red(`\nāœ— Error: ${error.message}\n`));
347
+ process.exit(1);
348
+ }
349
+ });
350
+
351
+ // List skills command
352
+ program
353
+ .command('list-skills')
354
+ .description('List available skills')
355
+ .option('-f, --format <type>', 'Output format (text|json)', 'text')
356
+ .option('--category <category>', 'Filter by category')
357
+ .action(async (options) => {
358
+ try {
359
+ console.log(chalk.bold('\nšŸ› ļø Available Skills\n'));
360
+
361
+ const engine = await createEngine(process.cwd());
362
+ const skillNames = engine.listSkills();
363
+
364
+ let skills = skillNames.map(name => {
365
+ const skill = engine.getSkill(name);
366
+ return { name, ...skill };
367
+ });
368
+
369
+ // Filter by category
370
+ if (options.category) {
371
+ skills = skills.filter(s =>
372
+ s.categories && s.categories.includes(options.category)
373
+ );
374
+ }
375
+
376
+ if (options.format === 'json') {
377
+ console.log(JSON.stringify(skills, null, 2));
378
+ } else {
379
+ if (skills.length === 0) {
380
+ console.log(chalk.yellow('No skills found'));
381
+ } else {
382
+ // Group by category
383
+ const byCategory = {};
384
+ for (const skill of skills) {
385
+ const cat = (skill.categories && skill.categories[0]) || 'other';
386
+ if (!byCategory[cat]) byCategory[cat] = [];
387
+ byCategory[cat].push(skill);
388
+ }
389
+
390
+ for (const [category, catSkills] of Object.entries(byCategory)) {
391
+ console.log(chalk.bold(` ${category}:`));
392
+ for (const skill of catSkills) {
393
+ console.log(chalk.cyan(` ${skill.name}`));
394
+ if (skill.keywords && skill.keywords.length > 0) {
395
+ console.log(chalk.dim(` Keywords: ${skill.keywords.join(', ')}`));
396
+ }
397
+ }
398
+ console.log('');
399
+ }
400
+ }
401
+ }
402
+
403
+ } catch (error) {
404
+ console.error(chalk.red(`\nāœ— Error: ${error.message}\n`));
405
+ process.exit(1);
406
+ }
407
+ });
408
+
409
+ // Status command
410
+ program
411
+ .command('status')
412
+ .description('Show orchestration engine status')
413
+ .option('-f, --format <type>', 'Output format (text|json)', 'text')
414
+ .action(async (options) => {
415
+ try {
416
+ console.log(chalk.bold('\nšŸ“Š Orchestration Status\n'));
417
+
418
+ const engine = await createEngine(process.cwd());
419
+ const status = engine.getStatus();
420
+
421
+ if (options.format === 'json') {
422
+ console.log(JSON.stringify(status, null, 2));
423
+ } else {
424
+ console.log(chalk.bold('Patterns:'));
425
+ console.log(` Registered: ${chalk.cyan(status.patterns.length)}`);
426
+ for (const p of status.patterns) {
427
+ console.log(` - ${p}`);
428
+ }
429
+
430
+ console.log(chalk.bold('\nSkills:'));
431
+ console.log(` Registered: ${chalk.cyan(status.skills.length)}`);
432
+
433
+ console.log(chalk.bold('\nActive Executions:'));
434
+ console.log(` Count: ${chalk.cyan(status.activeExecutions)}`);
435
+
436
+ if (status.contexts.length > 0) {
437
+ console.log(chalk.bold('\nActive Contexts:'));
438
+ for (const ctx of status.contexts) {
439
+ console.log(` - ${ctx.id}: ${ctx.task} (${ctx.status})`);
440
+ }
441
+ }
442
+ }
443
+
444
+ console.log('');
445
+
446
+ } catch (error) {
447
+ console.error(chalk.red(`\nāœ— Error: ${error.message}\n`));
448
+ process.exit(1);
449
+ }
450
+ });
451
+
452
+ program.parse(process.argv);
453
+
454
+ if (!process.argv.slice(2).length) {
455
+ program.outputHelp();
456
+ }