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
+ * SwarmPattern - Parallel skill execution pattern
3
+ *
4
+ * Enables concurrent execution of multiple skills with
5
+ * P-label task decomposition and dependency tracking.
6
+ */
7
+
8
+ const { BasePattern } = require('../pattern-registry');
9
+ const { PatternType, ExecutionContext, ExecutionStatus, Priority } = require('../orchestration-engine');
10
+
11
+ /**
12
+ * P-label priority levels for parallel execution
13
+ */
14
+ const PLabel = {
15
+ P0: 'P0', // Critical - must complete first (blocking)
16
+ P1: 'P1', // High priority - primary path
17
+ P2: 'P2', // Medium priority - secondary path
18
+ P3: 'P3' // Low priority - can be deferred
19
+ };
20
+
21
+ /**
22
+ * Execution strategy for swarm
23
+ */
24
+ const SwarmStrategy = {
25
+ ALL: 'all', // Wait for all to complete
26
+ FIRST: 'first', // Return after first success
27
+ MAJORITY: 'majority', // Return after majority complete
28
+ QUORUM: 'quorum' // Return after quorum achieved
29
+ };
30
+
31
+ /**
32
+ * SwarmPattern - Parallel skill execution
33
+ */
34
+ class SwarmPattern extends BasePattern {
35
+ constructor(options = {}) {
36
+ super({
37
+ name: PatternType.SWARM,
38
+ type: PatternType.SWARM,
39
+ description: 'Execute multiple skills concurrently with dependency tracking',
40
+ version: '1.0.0',
41
+ tags: ['parallel', 'concurrent', 'swarm', 'distributed'],
42
+ useCases: [
43
+ 'Parallel task execution',
44
+ 'Independent subtask processing',
45
+ 'Load distribution',
46
+ 'Multi-perspective analysis'
47
+ ],
48
+ complexity: 'high',
49
+ supportsParallel: true,
50
+ requiresHuman: false
51
+ });
52
+
53
+ this.options = {
54
+ strategy: options.strategy || SwarmStrategy.ALL,
55
+ maxConcurrent: options.maxConcurrent || 10,
56
+ timeout: options.timeout || 60000, // 60 seconds per task
57
+ retryFailed: options.retryFailed || false,
58
+ retryAttempts: options.retryAttempts || 3,
59
+ quorumThreshold: options.quorumThreshold || 0.5,
60
+ priorityOrder: options.priorityOrder || [PLabel.P0, PLabel.P1, PLabel.P2, PLabel.P3],
61
+ ...options
62
+ };
63
+ }
64
+
65
+ /**
66
+ * Validate the execution context
67
+ * @param {ExecutionContext} context - Execution context
68
+ * @param {OrchestrationEngine} engine - Orchestration engine
69
+ * @returns {object} Validation result
70
+ */
71
+ validate(context, engine) {
72
+ const errors = [];
73
+ const input = context.input;
74
+
75
+ // Check for tasks
76
+ if (!input.tasks || !Array.isArray(input.tasks)) {
77
+ errors.push('Swarm pattern requires input.tasks array');
78
+ } else if (input.tasks.length === 0) {
79
+ errors.push('Swarm pattern requires at least one task');
80
+ } else {
81
+ // Validate each task
82
+ for (let i = 0; i < input.tasks.length; i++) {
83
+ const task = input.tasks[i];
84
+ if (!task.skill) {
85
+ errors.push(`Task ${i} requires a skill name`);
86
+ } else if (!engine.getSkill(task.skill)) {
87
+ errors.push(`Unknown skill: ${task.skill}`);
88
+ }
89
+ }
90
+ }
91
+
92
+ // Validate dependencies
93
+ if (input.dependencies) {
94
+ const taskIds = new Set(input.tasks.map(t => t.id || t.skill));
95
+ for (const [taskId, deps] of Object.entries(input.dependencies)) {
96
+ if (!taskIds.has(taskId)) {
97
+ errors.push(`Dependency references unknown task: ${taskId}`);
98
+ }
99
+ for (const dep of deps) {
100
+ if (!taskIds.has(dep)) {
101
+ errors.push(`Dependency references unknown task: ${dep}`);
102
+ }
103
+ }
104
+ }
105
+ }
106
+
107
+ return {
108
+ valid: errors.length === 0,
109
+ errors
110
+ };
111
+ }
112
+
113
+ /**
114
+ * Execute swarm pattern
115
+ * @param {ExecutionContext} context - Execution context
116
+ * @param {OrchestrationEngine} engine - Orchestration engine
117
+ * @returns {Promise<object>} Execution result
118
+ */
119
+ async execute(context, engine) {
120
+ const validation = this.validate(context, engine);
121
+ if (!validation.valid) {
122
+ throw new Error(`Validation failed: ${validation.errors.join(', ')}`);
123
+ }
124
+
125
+ const { tasks, dependencies = {}, sharedContext = {} } = context.input;
126
+ const results = new Map();
127
+ const completed = new Set();
128
+ const failed = new Set();
129
+ const pending = new Set(tasks.map(t => t.id || t.skill));
130
+
131
+ engine.emit('swarmStarted', {
132
+ context,
133
+ totalTasks: tasks.length,
134
+ strategy: this.options.strategy
135
+ });
136
+
137
+ const startTime = Date.now();
138
+
139
+ try {
140
+ // Sort tasks by priority
141
+ const sortedTasks = this._sortByPriority(tasks);
142
+
143
+ // Execute tasks respecting dependencies
144
+ while (pending.size > 0) {
145
+ // Find ready tasks (dependencies satisfied)
146
+ const readyTasks = sortedTasks.filter(task => {
147
+ const taskId = task.id || task.skill;
148
+ if (!pending.has(taskId)) return false;
149
+
150
+ const deps = dependencies[taskId] || [];
151
+ return deps.every(dep => completed.has(dep));
152
+ });
153
+
154
+ if (readyTasks.length === 0 && pending.size > 0) {
155
+ // Circular dependency or missing dependency
156
+ throw new Error(`Cannot resolve dependencies for tasks: ${[...pending].join(', ')}`);
157
+ }
158
+
159
+ // Execute ready tasks in parallel (limited by maxConcurrent)
160
+ const batch = readyTasks.slice(0, this.options.maxConcurrent);
161
+
162
+ engine.emit('swarmBatchStarted', {
163
+ context,
164
+ batch: batch.map(t => t.id || t.skill),
165
+ pending: pending.size
166
+ });
167
+
168
+ const batchResults = await Promise.allSettled(
169
+ batch.map(task => this._executeTask(task, engine, context, sharedContext, results))
170
+ );
171
+
172
+ // Process results
173
+ for (let i = 0; i < batch.length; i++) {
174
+ const task = batch[i];
175
+ const taskId = task.id || task.skill;
176
+ const result = batchResults[i];
177
+
178
+ pending.delete(taskId);
179
+
180
+ if (result.status === 'fulfilled') {
181
+ results.set(taskId, result.value);
182
+ completed.add(taskId);
183
+
184
+ engine.emit('swarmTaskCompleted', {
185
+ context,
186
+ taskId,
187
+ result: result.value
188
+ });
189
+ } else {
190
+ failed.add(taskId);
191
+ results.set(taskId, { error: result.reason.message });
192
+
193
+ engine.emit('swarmTaskFailed', {
194
+ context,
195
+ taskId,
196
+ error: result.reason
197
+ });
198
+
199
+ // Retry logic
200
+ if (this.options.retryFailed && task.retryCount < this.options.retryAttempts) {
201
+ task.retryCount = (task.retryCount || 0) + 1;
202
+ pending.add(taskId);
203
+ failed.delete(taskId);
204
+ }
205
+ }
206
+ }
207
+
208
+ // Check early exit conditions
209
+ if (this._shouldExit(completed, failed, tasks.length)) {
210
+ break;
211
+ }
212
+ }
213
+
214
+ const duration = Date.now() - startTime;
215
+ const summary = this._createSummary(results, completed, failed, duration, tasks);
216
+
217
+ engine.emit('swarmCompleted', {
218
+ context,
219
+ results: Object.fromEntries(results),
220
+ summary
221
+ });
222
+
223
+ return {
224
+ results: Object.fromEntries(results),
225
+ completed: [...completed],
226
+ failed: [...failed],
227
+ summary
228
+ };
229
+
230
+ } catch (error) {
231
+ engine.emit('swarmFailed', {
232
+ context,
233
+ results: Object.fromEntries(results),
234
+ error
235
+ });
236
+ throw error;
237
+ }
238
+ }
239
+
240
+ /**
241
+ * Sort tasks by priority (P0 first)
242
+ * @private
243
+ */
244
+ _sortByPriority(tasks) {
245
+ const priorityOrder = this.options.priorityOrder;
246
+
247
+ return [...tasks].sort((a, b) => {
248
+ const aPriority = a.priority || PLabel.P2;
249
+ const bPriority = b.priority || PLabel.P2;
250
+ return priorityOrder.indexOf(aPriority) - priorityOrder.indexOf(bPriority);
251
+ });
252
+ }
253
+
254
+ /**
255
+ * Execute a single task
256
+ * @private
257
+ */
258
+ async _executeTask(task, engine, parentContext, sharedContext, previousResults) {
259
+ const taskId = task.id || task.skill;
260
+
261
+ const stepContext = new ExecutionContext({
262
+ task: `Swarm task: ${taskId}`,
263
+ skill: task.skill,
264
+ input: {
265
+ ...sharedContext,
266
+ ...task.input,
267
+ previousResults: Object.fromEntries(previousResults)
268
+ },
269
+ parentId: parentContext.id,
270
+ priority: this._mapPriority(task.priority),
271
+ metadata: {
272
+ pattern: PatternType.SWARM,
273
+ taskId,
274
+ priority: task.priority || PLabel.P2
275
+ }
276
+ });
277
+
278
+ parentContext.children.push(stepContext);
279
+
280
+ stepContext.start();
281
+
282
+ try {
283
+ const result = await Promise.race([
284
+ engine.executeSkill(task.skill, stepContext.input, parentContext),
285
+ this._timeout(this.options.timeout, taskId)
286
+ ]);
287
+
288
+ stepContext.complete(result);
289
+ return result;
290
+
291
+ } catch (error) {
292
+ stepContext.fail(error);
293
+ throw error;
294
+ }
295
+ }
296
+
297
+ /**
298
+ * Map P-label to internal priority
299
+ * @private
300
+ */
301
+ _mapPriority(pLabel) {
302
+ const mapping = {
303
+ [PLabel.P0]: Priority.CRITICAL,
304
+ [PLabel.P1]: Priority.HIGH,
305
+ [PLabel.P2]: Priority.MEDIUM,
306
+ [PLabel.P3]: Priority.LOW
307
+ };
308
+ return mapping[pLabel] || Priority.MEDIUM;
309
+ }
310
+
311
+ /**
312
+ * Create timeout promise
313
+ * @private
314
+ */
315
+ _timeout(ms, taskId) {
316
+ return new Promise((_, reject) => {
317
+ setTimeout(() => reject(new Error(`Task ${taskId} timed out after ${ms}ms`)), ms);
318
+ });
319
+ }
320
+
321
+ /**
322
+ * Check if swarm should exit early based on strategy
323
+ * @private
324
+ */
325
+ _shouldExit(completed, failed, total) {
326
+ switch (this.options.strategy) {
327
+ case SwarmStrategy.FIRST:
328
+ return completed.size >= 1;
329
+
330
+ case SwarmStrategy.MAJORITY:
331
+ return completed.size > total / 2;
332
+
333
+ case SwarmStrategy.QUORUM:
334
+ return completed.size >= total * this.options.quorumThreshold;
335
+
336
+ case SwarmStrategy.ALL:
337
+ default:
338
+ return false; // Continue until all complete
339
+ }
340
+ }
341
+
342
+ /**
343
+ * Create execution summary
344
+ * @private
345
+ */
346
+ _createSummary(results, completed, failed, duration, tasks) {
347
+ const total = tasks.length;
348
+ const successCount = completed.size;
349
+ const failCount = failed.size;
350
+ const pendingCount = total - successCount - failCount;
351
+
352
+ // Count by priority
353
+ const byPriority = {
354
+ [PLabel.P0]: { total: 0, completed: 0, failed: 0 },
355
+ [PLabel.P1]: { total: 0, completed: 0, failed: 0 },
356
+ [PLabel.P2]: { total: 0, completed: 0, failed: 0 },
357
+ [PLabel.P3]: { total: 0, completed: 0, failed: 0 }
358
+ };
359
+
360
+ for (const task of tasks) {
361
+ const priority = task.priority || PLabel.P2;
362
+ const taskId = task.id || task.skill;
363
+ byPriority[priority].total++;
364
+ if (completed.has(taskId)) byPriority[priority].completed++;
365
+ if (failed.has(taskId)) byPriority[priority].failed++;
366
+ }
367
+
368
+ return {
369
+ total,
370
+ completed: successCount,
371
+ failed: failCount,
372
+ pending: pendingCount,
373
+ duration,
374
+ successRate: total > 0 ? (successCount / total * 100).toFixed(1) + '%' : '0%',
375
+ strategy: this.options.strategy,
376
+ byPriority
377
+ };
378
+ }
379
+ }
380
+
381
+ /**
382
+ * Create a swarm pattern with custom options
383
+ * @param {object} options - Pattern options
384
+ * @returns {SwarmPattern} Swarm pattern instance
385
+ */
386
+ function createSwarmPattern(options = {}) {
387
+ return new SwarmPattern(options);
388
+ }
389
+
390
+ module.exports = {
391
+ SwarmPattern,
392
+ PLabel,
393
+ SwarmStrategy,
394
+ createSwarmPattern
395
+ };