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,319 @@
1
+ /**
2
+ * PatternRegistry - Registry for orchestration patterns
3
+ *
4
+ * Manages pattern lifecycle and provides pattern discovery
5
+ */
6
+
7
+ const { PatternType } = require('./orchestration-engine');
8
+
9
+ /**
10
+ * Pattern metadata
11
+ */
12
+ class PatternMetadata {
13
+ constructor(options = {}) {
14
+ this.name = options.name || '';
15
+ this.type = options.type || PatternType.SEQUENTIAL;
16
+ this.description = options.description || '';
17
+ this.version = options.version || '1.0.0';
18
+ this.author = options.author || 'MUSUBI';
19
+ this.tags = options.tags || [];
20
+ this.useCases = options.useCases || [];
21
+ this.complexity = options.complexity || 'medium'; // low, medium, high
22
+ this.supportsParallel = options.supportsParallel || false;
23
+ this.requiresHuman = options.requiresHuman || false;
24
+ }
25
+
26
+ matches(criteria = {}) {
27
+ if (criteria.type && this.type !== criteria.type) return false;
28
+ if (criteria.complexity && this.complexity !== criteria.complexity) return false;
29
+ if (criteria.supportsParallel !== undefined &&
30
+ this.supportsParallel !== criteria.supportsParallel) return false;
31
+ if (criteria.requiresHuman !== undefined &&
32
+ this.requiresHuman !== criteria.requiresHuman) return false;
33
+ if (criteria.tags && criteria.tags.length > 0) {
34
+ if (!criteria.tags.some(t => this.tags.includes(t))) return false;
35
+ }
36
+ return true;
37
+ }
38
+
39
+ toJSON() {
40
+ return {
41
+ name: this.name,
42
+ type: this.type,
43
+ description: this.description,
44
+ version: this.version,
45
+ author: this.author,
46
+ tags: this.tags,
47
+ useCases: this.useCases,
48
+ complexity: this.complexity,
49
+ supportsParallel: this.supportsParallel,
50
+ requiresHuman: this.requiresHuman
51
+ };
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Base pattern class
57
+ */
58
+ class BasePattern {
59
+ constructor(metadata = {}) {
60
+ this.metadata = new PatternMetadata(metadata);
61
+ }
62
+
63
+ /**
64
+ * Execute the pattern
65
+ * @param {ExecutionContext} context - Execution context
66
+ * @param {OrchestrationEngine} engine - Orchestration engine
67
+ * @returns {Promise<any>} Execution result
68
+ */
69
+ async execute(context, engine) {
70
+ throw new Error('Pattern must implement execute method');
71
+ }
72
+
73
+ /**
74
+ * Validate pattern can execute with given context
75
+ * @param {ExecutionContext} context - Execution context
76
+ * @param {OrchestrationEngine} engine - Orchestration engine
77
+ * @returns {object} Validation result
78
+ */
79
+ validate(context, engine) {
80
+ return { valid: true, errors: [] };
81
+ }
82
+
83
+ /**
84
+ * Get pattern name
85
+ * @returns {string} Pattern name
86
+ */
87
+ getName() {
88
+ return this.metadata.name;
89
+ }
90
+
91
+ /**
92
+ * Get pattern metadata
93
+ * @returns {PatternMetadata} Pattern metadata
94
+ */
95
+ getMetadata() {
96
+ return this.metadata;
97
+ }
98
+ }
99
+
100
+ /**
101
+ * PatternRegistry - Central registry for patterns
102
+ */
103
+ class PatternRegistry {
104
+ constructor() {
105
+ this.patterns = new Map();
106
+ this.metadata = new Map();
107
+ }
108
+
109
+ /**
110
+ * Register a pattern
111
+ * @param {string} name - Pattern name
112
+ * @param {BasePattern|object} pattern - Pattern implementation
113
+ * @param {object} metadata - Optional metadata override
114
+ * @returns {PatternRegistry} This registry for chaining
115
+ */
116
+ register(name, pattern, metadata = {}) {
117
+ if (!pattern) {
118
+ throw new Error(`Pattern '${name}' cannot be null`);
119
+ }
120
+
121
+ // Validate pattern has execute method
122
+ if (typeof pattern.execute !== 'function') {
123
+ throw new Error(`Pattern '${name}' must have an execute method`);
124
+ }
125
+
126
+ this.patterns.set(name, pattern);
127
+
128
+ // Extract or create metadata
129
+ const patternMeta = pattern.metadata || pattern.getMetadata?.() || {};
130
+ this.metadata.set(name, new PatternMetadata({
131
+ name,
132
+ ...patternMeta,
133
+ ...metadata
134
+ }));
135
+
136
+ return this;
137
+ }
138
+
139
+ /**
140
+ * Unregister a pattern
141
+ * @param {string} name - Pattern name
142
+ * @returns {boolean} True if pattern was removed
143
+ */
144
+ unregister(name) {
145
+ this.metadata.delete(name);
146
+ return this.patterns.delete(name);
147
+ }
148
+
149
+ /**
150
+ * Get a pattern by name
151
+ * @param {string} name - Pattern name
152
+ * @returns {object|null} Pattern or null
153
+ */
154
+ get(name) {
155
+ return this.patterns.get(name) || null;
156
+ }
157
+
158
+ /**
159
+ * Check if a pattern exists
160
+ * @param {string} name - Pattern name
161
+ * @returns {boolean} True if pattern exists
162
+ */
163
+ has(name) {
164
+ return this.patterns.has(name);
165
+ }
166
+
167
+ /**
168
+ * Get pattern metadata
169
+ * @param {string} name - Pattern name
170
+ * @returns {PatternMetadata|null} Metadata or null
171
+ */
172
+ getMetadata(name) {
173
+ return this.metadata.get(name) || null;
174
+ }
175
+
176
+ /**
177
+ * List all pattern names
178
+ * @returns {string[]} Pattern names
179
+ */
180
+ list() {
181
+ return Array.from(this.patterns.keys());
182
+ }
183
+
184
+ /**
185
+ * Find patterns matching criteria
186
+ * @param {object} criteria - Search criteria
187
+ * @returns {object[]} Matching patterns with metadata
188
+ */
189
+ find(criteria = {}) {
190
+ const results = [];
191
+
192
+ for (const [name, pattern] of this.patterns) {
193
+ const meta = this.metadata.get(name);
194
+ if (meta && meta.matches(criteria)) {
195
+ results.push({
196
+ name,
197
+ pattern,
198
+ metadata: meta
199
+ });
200
+ }
201
+ }
202
+
203
+ return results;
204
+ }
205
+
206
+ /**
207
+ * Find the best pattern for a task
208
+ * @param {string} task - Task description
209
+ * @returns {string|null} Best pattern name
210
+ */
211
+ findBestPattern(task) {
212
+ const taskLower = task.toLowerCase();
213
+
214
+ // Check for parallel keywords
215
+ if (taskLower.includes('parallel') ||
216
+ taskLower.includes('concurrent') ||
217
+ taskLower.includes('simultaneous')) {
218
+ const swarm = this.find({ supportsParallel: true });
219
+ if (swarm.length > 0) return swarm[0].name;
220
+ }
221
+
222
+ // Check for sequential keywords
223
+ if (taskLower.includes('sequential') ||
224
+ taskLower.includes('step by step') ||
225
+ taskLower.includes('one by one')) {
226
+ if (this.has(PatternType.SEQUENTIAL)) return PatternType.SEQUENTIAL;
227
+ }
228
+
229
+ // Check for collaboration keywords
230
+ if (taskLower.includes('discuss') ||
231
+ taskLower.includes('review') ||
232
+ taskLower.includes('collaborate')) {
233
+ if (this.has(PatternType.GROUP_CHAT)) return PatternType.GROUP_CHAT;
234
+ }
235
+
236
+ // Check for nested/hierarchical keywords
237
+ if (taskLower.includes('break down') ||
238
+ taskLower.includes('decompose') ||
239
+ taskLower.includes('hierarchical')) {
240
+ if (this.has(PatternType.NESTED)) return PatternType.NESTED;
241
+ }
242
+
243
+ // Check for human validation keywords
244
+ if (taskLower.includes('validate') ||
245
+ taskLower.includes('approve') ||
246
+ taskLower.includes('review')) {
247
+ if (this.has(PatternType.HUMAN_IN_LOOP)) return PatternType.HUMAN_IN_LOOP;
248
+ }
249
+
250
+ // Default to auto pattern
251
+ if (this.has(PatternType.AUTO)) return PatternType.AUTO;
252
+
253
+ // Fall back to sequential
254
+ if (this.has(PatternType.SEQUENTIAL)) return PatternType.SEQUENTIAL;
255
+
256
+ // Return first available pattern
257
+ const patterns = this.list();
258
+ return patterns.length > 0 ? patterns[0] : null;
259
+ }
260
+
261
+ /**
262
+ * Register all patterns with an orchestration engine
263
+ * @param {OrchestrationEngine} engine - Engine to register with
264
+ */
265
+ registerWithEngine(engine) {
266
+ for (const [name, pattern] of this.patterns) {
267
+ engine.registerPattern(name, pattern);
268
+ }
269
+ }
270
+
271
+ /**
272
+ * Get registry summary
273
+ * @returns {object} Summary of registered patterns
274
+ */
275
+ getSummary() {
276
+ const summary = {
277
+ total: this.patterns.size,
278
+ patterns: [],
279
+ byType: {},
280
+ byComplexity: {}
281
+ };
282
+
283
+ for (const [name, meta] of this.metadata) {
284
+ summary.patterns.push(meta.toJSON());
285
+
286
+ // Count by type
287
+ summary.byType[meta.type] = (summary.byType[meta.type] || 0) + 1;
288
+
289
+ // Count by complexity
290
+ summary.byComplexity[meta.complexity] =
291
+ (summary.byComplexity[meta.complexity] || 0) + 1;
292
+ }
293
+
294
+ return summary;
295
+ }
296
+
297
+ /**
298
+ * Clear all patterns
299
+ */
300
+ clear() {
301
+ this.patterns.clear();
302
+ this.metadata.clear();
303
+ }
304
+ }
305
+
306
+ /**
307
+ * Create a default registry with built-in patterns
308
+ * @returns {PatternRegistry} Registry with default patterns
309
+ */
310
+ function createDefaultRegistry() {
311
+ return new PatternRegistry();
312
+ }
313
+
314
+ module.exports = {
315
+ PatternRegistry,
316
+ PatternMetadata,
317
+ BasePattern,
318
+ createDefaultRegistry
319
+ };
@@ -0,0 +1,386 @@
1
+ /**
2
+ * AutoPattern - Automatic skill selection pattern
3
+ *
4
+ * Analyzes the task and automatically selects the most appropriate
5
+ * skill to execute. Uses skill metadata and keywords for matching.
6
+ */
7
+
8
+ const { BasePattern } = require('../pattern-registry');
9
+ const { PatternType, ExecutionContext, ExecutionStatus } = require('../orchestration-engine');
10
+
11
+ /**
12
+ * Skill match confidence levels
13
+ */
14
+ const ConfidenceLevel = {
15
+ HIGH: 'high', // >= 0.8
16
+ MEDIUM: 'medium', // >= 0.5
17
+ LOW: 'low', // >= 0.3
18
+ NONE: 'none' // < 0.3
19
+ };
20
+
21
+ /**
22
+ * AutoPattern - Automatic skill selection and execution
23
+ */
24
+ class AutoPattern extends BasePattern {
25
+ constructor(options = {}) {
26
+ super({
27
+ name: PatternType.AUTO,
28
+ type: PatternType.AUTO,
29
+ description: 'Automatically select and execute the best skill for a task',
30
+ version: '1.0.0',
31
+ tags: ['intelligent', 'automatic', 'routing'],
32
+ useCases: [
33
+ 'Dynamic task routing',
34
+ 'Intelligent skill selection',
35
+ 'Natural language task processing'
36
+ ],
37
+ complexity: 'medium',
38
+ supportsParallel: false,
39
+ requiresHuman: false
40
+ });
41
+
42
+ this.options = {
43
+ minConfidence: options.minConfidence || 0.3,
44
+ fallbackSkill: options.fallbackSkill || null,
45
+ multiMatch: options.multiMatch || false, // Execute multiple matching skills
46
+ maxMatches: options.maxMatches || 3,
47
+ ...options
48
+ };
49
+
50
+ // Skill category keywords for classification
51
+ this.categoryKeywords = {
52
+ requirements: ['requirement', 'need', 'user story', 'feature', 'specification', 'ears'],
53
+ design: ['design', 'architecture', 'component', 'diagram', 'c4', 'uml'],
54
+ implementation: ['implement', 'code', 'develop', 'build', 'create', 'programming'],
55
+ testing: ['test', 'qa', 'quality', 'verify', 'validate', 'bug'],
56
+ documentation: ['document', 'doc', 'readme', 'guide', 'tutorial'],
57
+ devops: ['deploy', 'ci', 'cd', 'pipeline', 'infrastructure', 'kubernetes'],
58
+ security: ['security', 'vulnerability', 'authentication', 'authorization'],
59
+ performance: ['performance', 'optimize', 'benchmark', 'profiling'],
60
+ analysis: ['analyze', 'review', 'assess', 'evaluate', 'audit'],
61
+ research: ['research', 'investigate', 'explore', 'study']
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
+
74
+ if (!context.task && !context.input?.task) {
75
+ errors.push('Auto pattern requires a task description');
76
+ }
77
+
78
+ if (engine.listSkills().length === 0) {
79
+ errors.push('No skills registered with engine');
80
+ }
81
+
82
+ return {
83
+ valid: errors.length === 0,
84
+ errors
85
+ };
86
+ }
87
+
88
+ /**
89
+ * Execute auto pattern - select and run best skill
90
+ * @param {ExecutionContext} context - Execution context
91
+ * @param {OrchestrationEngine} engine - Orchestration engine
92
+ * @returns {Promise<object>} Execution result
93
+ */
94
+ async execute(context, engine) {
95
+ const validation = this.validate(context, engine);
96
+ if (!validation.valid) {
97
+ throw new Error(`Validation failed: ${validation.errors.join(', ')}`);
98
+ }
99
+
100
+ const task = context.task || context.input?.task || '';
101
+ const input = context.input?.skillInput || context.input || {};
102
+
103
+ engine.emit('autoPatternStarted', {
104
+ context,
105
+ task
106
+ });
107
+
108
+ // Find matching skills
109
+ const matches = this._findMatchingSkills(task, engine);
110
+
111
+ engine.emit('autoPatternMatched', {
112
+ context,
113
+ task,
114
+ matches: matches.map(m => ({ skill: m.skill, confidence: m.confidence }))
115
+ });
116
+
117
+ if (matches.length === 0) {
118
+ // No matches found
119
+ if (this.options.fallbackSkill && engine.getSkill(this.options.fallbackSkill)) {
120
+ engine.emit('autoPatternFallback', {
121
+ context,
122
+ fallbackSkill: this.options.fallbackSkill
123
+ });
124
+
125
+ return this._executeSingleSkill(
126
+ this.options.fallbackSkill,
127
+ input,
128
+ context,
129
+ engine,
130
+ { confidence: 0, reason: 'fallback' }
131
+ );
132
+ }
133
+
134
+ throw new Error(`No matching skill found for task: ${task}`);
135
+ }
136
+
137
+ // Execute based on configuration
138
+ if (this.options.multiMatch && matches.length > 1) {
139
+ return this._executeMultipleSkills(matches, input, context, engine);
140
+ }
141
+
142
+ // Execute best match
143
+ const bestMatch = matches[0];
144
+ return this._executeSingleSkill(
145
+ bestMatch.skill,
146
+ input,
147
+ context,
148
+ engine,
149
+ bestMatch
150
+ );
151
+ }
152
+
153
+ /**
154
+ * Find matching skills for a task
155
+ * @private
156
+ */
157
+ _findMatchingSkills(task, engine) {
158
+ const taskLower = task.toLowerCase();
159
+ const words = this._tokenize(taskLower);
160
+ const matches = [];
161
+
162
+ for (const skillName of engine.listSkills()) {
163
+ const skill = engine.getSkill(skillName);
164
+ const score = this._calculateMatchScore(taskLower, words, skillName, skill);
165
+
166
+ if (score >= this.options.minConfidence) {
167
+ matches.push({
168
+ skill: skillName,
169
+ confidence: score,
170
+ confidenceLevel: this._getConfidenceLevel(score),
171
+ matchedKeywords: this._getMatchedKeywords(taskLower, skill)
172
+ });
173
+ }
174
+ }
175
+
176
+ // Sort by confidence descending
177
+ matches.sort((a, b) => b.confidence - a.confidence);
178
+
179
+ // Limit matches
180
+ return matches.slice(0, this.options.maxMatches);
181
+ }
182
+
183
+ /**
184
+ * Calculate match score for a skill
185
+ * @private
186
+ */
187
+ _calculateMatchScore(taskLower, words, skillName, skill) {
188
+ let score = 0;
189
+ let maxScore = 0;
190
+
191
+ // Skill name match
192
+ maxScore += 0.3;
193
+ const skillNameLower = skillName.toLowerCase().replace(/-/g, ' ');
194
+ if (taskLower.includes(skillNameLower)) {
195
+ score += 0.3;
196
+ } else {
197
+ // Partial name match
198
+ const nameWords = skillNameLower.split(' ');
199
+ const matchedNameWords = nameWords.filter(w => taskLower.includes(w));
200
+ score += 0.3 * (matchedNameWords.length / nameWords.length);
201
+ }
202
+
203
+ // Keywords match
204
+ const keywords = skill?.keywords || [];
205
+ if (keywords.length > 0) {
206
+ maxScore += 0.4;
207
+ const matchedKeywords = keywords.filter(k =>
208
+ taskLower.includes(k.toLowerCase())
209
+ );
210
+ score += 0.4 * (matchedKeywords.length / keywords.length);
211
+ }
212
+
213
+ // Category match
214
+ maxScore += 0.2;
215
+ const categories = skill?.categories || [];
216
+ for (const category of categories) {
217
+ const categoryKw = this.categoryKeywords[category] || [];
218
+ if (categoryKw.some(kw => taskLower.includes(kw))) {
219
+ score += 0.2;
220
+ break;
221
+ }
222
+ }
223
+
224
+ // Description match
225
+ const description = skill?.description || '';
226
+ if (description) {
227
+ maxScore += 0.1;
228
+ const descWords = this._tokenize(description.toLowerCase());
229
+ const commonWords = words.filter(w => descWords.includes(w));
230
+ score += 0.1 * Math.min(1, commonWords.length / 3);
231
+ }
232
+
233
+ // Normalize score
234
+ return maxScore > 0 ? score / maxScore : 0;
235
+ }
236
+
237
+ /**
238
+ * Get confidence level from score
239
+ * @private
240
+ */
241
+ _getConfidenceLevel(score) {
242
+ if (score >= 0.8) return ConfidenceLevel.HIGH;
243
+ if (score >= 0.5) return ConfidenceLevel.MEDIUM;
244
+ if (score >= 0.3) return ConfidenceLevel.LOW;
245
+ return ConfidenceLevel.NONE;
246
+ }
247
+
248
+ /**
249
+ * Get matched keywords
250
+ * @private
251
+ */
252
+ _getMatchedKeywords(taskLower, skill) {
253
+ const keywords = skill?.keywords || [];
254
+ return keywords.filter(k => taskLower.includes(k.toLowerCase()));
255
+ }
256
+
257
+ /**
258
+ * Tokenize text into words
259
+ * @private
260
+ */
261
+ _tokenize(text) {
262
+ return text
263
+ .split(/\s+/)
264
+ .map(w => w.replace(/[^\w]/g, ''))
265
+ .filter(w => w.length > 2);
266
+ }
267
+
268
+ /**
269
+ * Execute a single skill
270
+ * @private
271
+ */
272
+ async _executeSingleSkill(skillName, input, context, engine, matchInfo) {
273
+ const stepContext = new ExecutionContext({
274
+ task: `Auto-selected: ${skillName}`,
275
+ skill: skillName,
276
+ input,
277
+ parentId: context.id,
278
+ metadata: {
279
+ pattern: PatternType.AUTO,
280
+ confidence: matchInfo.confidence,
281
+ confidenceLevel: matchInfo.confidenceLevel,
282
+ matchedKeywords: matchInfo.matchedKeywords
283
+ }
284
+ });
285
+
286
+ context.children.push(stepContext);
287
+
288
+ try {
289
+ stepContext.start();
290
+ const output = await engine.executeSkill(skillName, input, context);
291
+ stepContext.complete(output);
292
+
293
+ engine.emit('autoPatternCompleted', {
294
+ context,
295
+ selectedSkill: skillName,
296
+ confidence: matchInfo.confidence,
297
+ output
298
+ });
299
+
300
+ return {
301
+ selectedSkill: skillName,
302
+ confidence: matchInfo.confidence,
303
+ confidenceLevel: matchInfo.confidenceLevel,
304
+ output,
305
+ multiMatch: false
306
+ };
307
+
308
+ } catch (error) {
309
+ stepContext.fail(error);
310
+ throw error;
311
+ }
312
+ }
313
+
314
+ /**
315
+ * Execute multiple matching skills
316
+ * @private
317
+ */
318
+ async _executeMultipleSkills(matches, input, context, engine) {
319
+ const results = [];
320
+
321
+ for (const match of matches) {
322
+ const stepContext = new ExecutionContext({
323
+ task: `Auto-selected (multi): ${match.skill}`,
324
+ skill: match.skill,
325
+ input,
326
+ parentId: context.id,
327
+ metadata: {
328
+ pattern: PatternType.AUTO,
329
+ confidence: match.confidence,
330
+ multiMatch: true
331
+ }
332
+ });
333
+
334
+ context.children.push(stepContext);
335
+
336
+ try {
337
+ stepContext.start();
338
+ const output = await engine.executeSkill(match.skill, input, context);
339
+ stepContext.complete(output);
340
+
341
+ results.push({
342
+ skill: match.skill,
343
+ confidence: match.confidence,
344
+ status: ExecutionStatus.COMPLETED,
345
+ output
346
+ });
347
+
348
+ } catch (error) {
349
+ stepContext.fail(error);
350
+ results.push({
351
+ skill: match.skill,
352
+ confidence: match.confidence,
353
+ status: ExecutionStatus.FAILED,
354
+ error: error.message
355
+ });
356
+ }
357
+ }
358
+
359
+ engine.emit('autoPatternCompleted', {
360
+ context,
361
+ results,
362
+ multiMatch: true
363
+ });
364
+
365
+ return {
366
+ selectedSkills: matches.map(m => m.skill),
367
+ results,
368
+ multiMatch: true
369
+ };
370
+ }
371
+ }
372
+
373
+ /**
374
+ * Create an auto pattern with custom options
375
+ * @param {object} options - Pattern options
376
+ * @returns {AutoPattern} Auto pattern instance
377
+ */
378
+ function createAutoPattern(options = {}) {
379
+ return new AutoPattern(options);
380
+ }
381
+
382
+ module.exports = {
383
+ AutoPattern,
384
+ ConfidenceLevel,
385
+ createAutoPattern
386
+ };