musubi-sdd 3.10.0 → 5.1.0

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 (44) hide show
  1. package/README.md +24 -19
  2. package/package.json +1 -1
  3. package/src/agents/agent-loop.js +532 -0
  4. package/src/agents/agentic/code-generator.js +767 -0
  5. package/src/agents/agentic/code-reviewer.js +698 -0
  6. package/src/agents/agentic/index.js +43 -0
  7. package/src/agents/function-tool.js +432 -0
  8. package/src/agents/index.js +45 -0
  9. package/src/agents/schema-generator.js +514 -0
  10. package/src/analyzers/ast-extractor.js +870 -0
  11. package/src/analyzers/context-optimizer.js +681 -0
  12. package/src/analyzers/repository-map.js +692 -0
  13. package/src/integrations/index.js +7 -1
  14. package/src/integrations/mcp/index.js +175 -0
  15. package/src/integrations/mcp/mcp-context-provider.js +472 -0
  16. package/src/integrations/mcp/mcp-discovery.js +436 -0
  17. package/src/integrations/mcp/mcp-tool-registry.js +467 -0
  18. package/src/integrations/mcp-connector.js +818 -0
  19. package/src/integrations/tool-discovery.js +589 -0
  20. package/src/managers/index.js +7 -0
  21. package/src/managers/skill-tools.js +565 -0
  22. package/src/monitoring/cost-tracker.js +7 -0
  23. package/src/monitoring/incident-manager.js +10 -0
  24. package/src/monitoring/observability.js +10 -0
  25. package/src/monitoring/quality-dashboard.js +491 -0
  26. package/src/monitoring/release-manager.js +10 -0
  27. package/src/orchestration/agent-skill-binding.js +655 -0
  28. package/src/orchestration/error-handler.js +827 -0
  29. package/src/orchestration/index.js +235 -1
  30. package/src/orchestration/mcp-tool-adapters.js +896 -0
  31. package/src/orchestration/reasoning/index.js +58 -0
  32. package/src/orchestration/reasoning/planning-engine.js +831 -0
  33. package/src/orchestration/reasoning/reasoning-engine.js +710 -0
  34. package/src/orchestration/reasoning/self-correction.js +751 -0
  35. package/src/orchestration/skill-executor.js +665 -0
  36. package/src/orchestration/skill-registry.js +650 -0
  37. package/src/orchestration/workflow-examples.js +1072 -0
  38. package/src/orchestration/workflow-executor.js +779 -0
  39. package/src/phase4-integration.js +248 -0
  40. package/src/phase5-integration.js +402 -0
  41. package/src/steering/steering-auto-update.js +572 -0
  42. package/src/steering/steering-validator.js +547 -0
  43. package/src/templates/template-constraints.js +646 -0
  44. package/src/validators/advanced-validation.js +580 -0
@@ -0,0 +1,580 @@
1
+ /**
2
+ * Advanced Validation Engine
3
+ * クロスアーティファクト一貫性検証と仕様ギャップ検出
4
+ *
5
+ * @module validators/advanced-validation
6
+ */
7
+
8
+ const EventEmitter = require('events');
9
+
10
+ /**
11
+ * Validation types
12
+ */
13
+ const VALIDATION_TYPE = {
14
+ CROSS_ARTIFACT: 'cross-artifact',
15
+ GAP_DETECTION: 'gap-detection',
16
+ TRACEABILITY: 'traceability',
17
+ CONSISTENCY: 'consistency',
18
+ COMPLETENESS: 'completeness'
19
+ };
20
+
21
+ /**
22
+ * Artifact types
23
+ */
24
+ const ARTIFACT_TYPE = {
25
+ REQUIREMENT: 'requirement',
26
+ DESIGN: 'design',
27
+ IMPLEMENTATION: 'implementation',
28
+ TEST: 'test',
29
+ STEERING: 'steering',
30
+ DOCUMENTATION: 'documentation'
31
+ };
32
+
33
+ /**
34
+ * Gap severity levels
35
+ */
36
+ const GAP_SEVERITY = {
37
+ CRITICAL: 'critical',
38
+ MAJOR: 'major',
39
+ MINOR: 'minor',
40
+ INFO: 'info'
41
+ };
42
+
43
+ /**
44
+ * Advanced Validation Engine
45
+ */
46
+ class AdvancedValidation extends EventEmitter {
47
+ /**
48
+ * @param {Object} options
49
+ * @param {boolean} options.strict - Strict mode
50
+ * @param {Object} options.rules - Custom validation rules
51
+ */
52
+ constructor(options = {}) {
53
+ super();
54
+
55
+ this.strict = options.strict ?? false;
56
+ this.customRules = new Map();
57
+ this.artifacts = new Map();
58
+ this.validationHistory = [];
59
+ this.traceabilityMatrix = new Map();
60
+
61
+ // Load custom rules
62
+ if (options.rules) {
63
+ for (const [name, rule] of Object.entries(options.rules)) {
64
+ this.addRule(name, rule);
65
+ }
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Register an artifact for validation
71
+ * @param {string} id - Artifact identifier
72
+ * @param {Object} artifact - Artifact data
73
+ */
74
+ registerArtifact(id, artifact) {
75
+ if (!artifact.type || !Object.values(ARTIFACT_TYPE).includes(artifact.type)) {
76
+ throw new Error(`Invalid artifact type: ${artifact.type}`);
77
+ }
78
+
79
+ this.artifacts.set(id, {
80
+ id,
81
+ ...artifact,
82
+ registeredAt: new Date().toISOString()
83
+ });
84
+
85
+ this.emit('artifact-registered', { id, artifact });
86
+ }
87
+
88
+ /**
89
+ * Unregister an artifact
90
+ * @param {string} id
91
+ */
92
+ unregisterArtifact(id) {
93
+ this.artifacts.delete(id);
94
+ this.traceabilityMatrix.delete(id);
95
+ }
96
+
97
+ /**
98
+ * Add a traceability link
99
+ * @param {string} sourceId - Source artifact ID
100
+ * @param {string} targetId - Target artifact ID
101
+ * @param {string} linkType - Type of link
102
+ */
103
+ addTraceLink(sourceId, targetId, linkType = 'implements') {
104
+ if (!this.artifacts.has(sourceId)) {
105
+ throw new Error(`Source artifact not found: ${sourceId}`);
106
+ }
107
+ if (!this.artifacts.has(targetId)) {
108
+ throw new Error(`Target artifact not found: ${targetId}`);
109
+ }
110
+
111
+ if (!this.traceabilityMatrix.has(sourceId)) {
112
+ this.traceabilityMatrix.set(sourceId, []);
113
+ }
114
+
115
+ this.traceabilityMatrix.get(sourceId).push({
116
+ target: targetId,
117
+ type: linkType,
118
+ createdAt: new Date().toISOString()
119
+ });
120
+ }
121
+
122
+ /**
123
+ * Validate cross-artifact consistency
124
+ * @param {Object} options
125
+ * @returns {Object}
126
+ */
127
+ validateCrossArtifact(options = {}) {
128
+ const issues = [];
129
+ const validated = [];
130
+
131
+ // Check for orphaned artifacts (no trace links)
132
+ for (const [id, artifact] of this.artifacts) {
133
+ const hasIncoming = this.hasIncomingLinks(id);
134
+ const hasOutgoing = this.traceabilityMatrix.has(id);
135
+
136
+ if (!hasIncoming && !hasOutgoing && artifact.type !== ARTIFACT_TYPE.REQUIREMENT) {
137
+ issues.push({
138
+ type: 'orphaned',
139
+ artifactId: id,
140
+ artifactType: artifact.type,
141
+ severity: GAP_SEVERITY.MAJOR,
142
+ message: `Artifact "${id}" has no traceability links`
143
+ });
144
+ }
145
+
146
+ validated.push(id);
147
+ }
148
+
149
+ // Check for broken links
150
+ for (const [sourceId, links] of this.traceabilityMatrix) {
151
+ for (const link of links) {
152
+ if (!this.artifacts.has(link.target)) {
153
+ issues.push({
154
+ type: 'broken-link',
155
+ sourceId,
156
+ targetId: link.target,
157
+ severity: GAP_SEVERITY.CRITICAL,
158
+ message: `Broken link: ${sourceId} -> ${link.target}`
159
+ });
160
+ }
161
+ }
162
+ }
163
+
164
+ // Check artifact type consistency
165
+ for (const [sourceId, links] of this.traceabilityMatrix) {
166
+ const sourceArtifact = this.artifacts.get(sourceId);
167
+ for (const link of links) {
168
+ const targetArtifact = this.artifacts.get(link.target);
169
+ if (targetArtifact) {
170
+ const valid = this.validateLinkTypes(sourceArtifact.type, targetArtifact.type, link.type);
171
+ if (!valid) {
172
+ issues.push({
173
+ type: 'invalid-link-type',
174
+ sourceId,
175
+ targetId: link.target,
176
+ linkType: link.type,
177
+ severity: GAP_SEVERITY.MINOR,
178
+ message: `Unusual link: ${sourceArtifact.type} -[${link.type}]-> ${targetArtifact.type}`
179
+ });
180
+ }
181
+ }
182
+ }
183
+ }
184
+
185
+ const result = {
186
+ type: VALIDATION_TYPE.CROSS_ARTIFACT,
187
+ valid: issues.filter(i => i.severity === GAP_SEVERITY.CRITICAL).length === 0,
188
+ issues,
189
+ validated,
190
+ timestamp: new Date().toISOString()
191
+ };
192
+
193
+ this.validationHistory.push(result);
194
+ this.emit('validated', result);
195
+
196
+ return result;
197
+ }
198
+
199
+ /**
200
+ * Check if artifact has incoming links
201
+ */
202
+ hasIncomingLinks(targetId) {
203
+ for (const [, links] of this.traceabilityMatrix) {
204
+ if (links.some(l => l.target === targetId)) {
205
+ return true;
206
+ }
207
+ }
208
+ return false;
209
+ }
210
+
211
+ /**
212
+ * Validate link type combinations
213
+ */
214
+ validateLinkTypes(sourceType, targetType, linkType) {
215
+ const validCombinations = {
216
+ 'requirement-design': ['implements', 'addresses', 'derives'],
217
+ 'design-implementation': ['implements', 'realizes'],
218
+ 'implementation-test': ['tests', 'verifies'],
219
+ 'requirement-test': ['verifies', 'validates']
220
+ };
221
+
222
+ const key = `${sourceType}-${targetType}`;
223
+ const reverseKey = `${targetType}-${sourceType}`;
224
+
225
+ const valid = validCombinations[key] || validCombinations[reverseKey];
226
+ return !valid || valid.includes(linkType);
227
+ }
228
+
229
+ /**
230
+ * Detect specification gaps
231
+ * @param {Object} options
232
+ * @returns {Object}
233
+ */
234
+ detectGaps(options = {}) {
235
+ const gaps = [];
236
+
237
+ // Requirements without design
238
+ const requirements = this.getArtifactsByType(ARTIFACT_TYPE.REQUIREMENT);
239
+ const designs = this.getArtifactsByType(ARTIFACT_TYPE.DESIGN);
240
+ const implementations = this.getArtifactsByType(ARTIFACT_TYPE.IMPLEMENTATION);
241
+ const tests = this.getArtifactsByType(ARTIFACT_TYPE.TEST);
242
+
243
+ for (const req of requirements) {
244
+ const hasDesign = this.hasLinkToType(req.id, ARTIFACT_TYPE.DESIGN);
245
+ if (!hasDesign) {
246
+ gaps.push({
247
+ type: 'missing-design',
248
+ artifactId: req.id,
249
+ severity: GAP_SEVERITY.MAJOR,
250
+ message: `Requirement "${req.id}" has no associated design`
251
+ });
252
+ }
253
+ }
254
+
255
+ // Designs without implementation
256
+ for (const design of designs) {
257
+ const hasImpl = this.hasLinkToType(design.id, ARTIFACT_TYPE.IMPLEMENTATION);
258
+ if (!hasImpl) {
259
+ gaps.push({
260
+ type: 'missing-implementation',
261
+ artifactId: design.id,
262
+ severity: GAP_SEVERITY.MAJOR,
263
+ message: `Design "${design.id}" has no associated implementation`
264
+ });
265
+ }
266
+ }
267
+
268
+ // Implementations without tests
269
+ for (const impl of implementations) {
270
+ const hasTest = this.hasLinkToType(impl.id, ARTIFACT_TYPE.TEST);
271
+ if (!hasTest) {
272
+ gaps.push({
273
+ type: 'missing-test',
274
+ artifactId: impl.id,
275
+ severity: GAP_SEVERITY.MINOR,
276
+ message: `Implementation "${impl.id}" has no associated tests`
277
+ });
278
+ }
279
+ }
280
+
281
+ // Check completeness
282
+ const completeness = {
283
+ requirements: requirements.length,
284
+ designs: designs.length,
285
+ implementations: implementations.length,
286
+ tests: tests.length,
287
+ coverage: this.calculateCoverage()
288
+ };
289
+
290
+ const result = {
291
+ type: VALIDATION_TYPE.GAP_DETECTION,
292
+ gaps,
293
+ completeness,
294
+ gapCount: gaps.length,
295
+ criticalGaps: gaps.filter(g => g.severity === GAP_SEVERITY.CRITICAL).length,
296
+ timestamp: new Date().toISOString()
297
+ };
298
+
299
+ this.validationHistory.push(result);
300
+ this.emit('gaps-detected', result);
301
+
302
+ return result;
303
+ }
304
+
305
+ /**
306
+ * Get artifacts by type
307
+ */
308
+ getArtifactsByType(type) {
309
+ return Array.from(this.artifacts.values()).filter(a => a.type === type);
310
+ }
311
+
312
+ /**
313
+ * Check if artifact has link to specific type
314
+ */
315
+ hasLinkToType(artifactId, targetType) {
316
+ const links = this.traceabilityMatrix.get(artifactId) || [];
317
+ for (const link of links) {
318
+ const target = this.artifacts.get(link.target);
319
+ if (target && target.type === targetType) {
320
+ return true;
321
+ }
322
+ }
323
+ return false;
324
+ }
325
+
326
+ /**
327
+ * Calculate traceability coverage
328
+ */
329
+ calculateCoverage() {
330
+ const total = this.artifacts.size;
331
+ if (total === 0) return 100;
332
+
333
+ let linked = 0;
334
+ for (const [id] of this.artifacts) {
335
+ if (this.traceabilityMatrix.has(id) || this.hasIncomingLinks(id)) {
336
+ linked++;
337
+ }
338
+ }
339
+
340
+ return Math.round((linked / total) * 100);
341
+ }
342
+
343
+ /**
344
+ * Validate traceability
345
+ * @returns {Object}
346
+ */
347
+ validateTraceability() {
348
+ const issues = [];
349
+ const matrix = {};
350
+
351
+ // Build traceability matrix view
352
+ for (const [sourceId, links] of this.traceabilityMatrix) {
353
+ const source = this.artifacts.get(sourceId);
354
+ if (!matrix[source?.type]) {
355
+ matrix[source?.type] = {};
356
+ }
357
+
358
+ for (const link of links) {
359
+ const target = this.artifacts.get(link.target);
360
+ if (!matrix[source?.type][target?.type]) {
361
+ matrix[source?.type][target?.type] = 0;
362
+ }
363
+ matrix[source?.type][target?.type]++;
364
+ }
365
+ }
366
+
367
+ // Check for bidirectional traceability
368
+ for (const [sourceId, links] of this.traceabilityMatrix) {
369
+ for (const link of links) {
370
+ const reverseLinks = this.traceabilityMatrix.get(link.target) || [];
371
+ const hasReverse = reverseLinks.some(l => l.target === sourceId);
372
+ if (!hasReverse && this.strict) {
373
+ issues.push({
374
+ type: 'unidirectional',
375
+ sourceId,
376
+ targetId: link.target,
377
+ severity: GAP_SEVERITY.INFO,
378
+ message: `Unidirectional link: ${sourceId} -> ${link.target}`
379
+ });
380
+ }
381
+ }
382
+ }
383
+
384
+ const coverage = this.calculateCoverage();
385
+
386
+ const result = {
387
+ type: VALIDATION_TYPE.TRACEABILITY,
388
+ valid: issues.length === 0,
389
+ issues,
390
+ matrix,
391
+ coverage,
392
+ artifactCount: this.artifacts.size,
393
+ linkCount: this.countLinks(),
394
+ timestamp: new Date().toISOString()
395
+ };
396
+
397
+ this.validationHistory.push(result);
398
+ return result;
399
+ }
400
+
401
+ /**
402
+ * Count total links
403
+ */
404
+ countLinks() {
405
+ let count = 0;
406
+ for (const [, links] of this.traceabilityMatrix) {
407
+ count += links.length;
408
+ }
409
+ return count;
410
+ }
411
+
412
+ /**
413
+ * Add a custom validation rule
414
+ * @param {string} name
415
+ * @param {Object} rule
416
+ */
417
+ addRule(name, rule) {
418
+ if (!rule.validate || typeof rule.validate !== 'function') {
419
+ throw new Error('Rule must have a validate function');
420
+ }
421
+ this.customRules.set(name, {
422
+ severity: GAP_SEVERITY.MINOR,
423
+ ...rule
424
+ });
425
+ }
426
+
427
+ /**
428
+ * Run all validations
429
+ * @returns {Object}
430
+ */
431
+ runAllValidations() {
432
+ const crossArtifact = this.validateCrossArtifact();
433
+ const gaps = this.detectGaps();
434
+ const traceability = this.validateTraceability();
435
+
436
+ // Run custom rules
437
+ const customResults = [];
438
+ for (const [name, rule] of this.customRules) {
439
+ try {
440
+ const result = rule.validate(this.artifacts, this.traceabilityMatrix);
441
+ customResults.push({
442
+ name,
443
+ ...result
444
+ });
445
+ } catch (error) {
446
+ customResults.push({
447
+ name,
448
+ error: error.message
449
+ });
450
+ }
451
+ }
452
+
453
+ const allIssues = [
454
+ ...crossArtifact.issues,
455
+ ...gaps.gaps,
456
+ ...traceability.issues
457
+ ];
458
+
459
+ const overallValid = allIssues.filter(i =>
460
+ i.severity === GAP_SEVERITY.CRITICAL
461
+ ).length === 0;
462
+
463
+ return {
464
+ valid: overallValid,
465
+ summary: {
466
+ crossArtifact: crossArtifact.valid,
467
+ gaps: gaps.gapCount === 0,
468
+ traceability: traceability.valid
469
+ },
470
+ crossArtifact,
471
+ gaps,
472
+ traceability,
473
+ customRules: customResults,
474
+ totalIssues: allIssues.length,
475
+ criticalIssues: allIssues.filter(i => i.severity === GAP_SEVERITY.CRITICAL).length,
476
+ timestamp: new Date().toISOString()
477
+ };
478
+ }
479
+
480
+ /**
481
+ * Get validation history
482
+ * @param {Object} filter
483
+ * @returns {Array}
484
+ */
485
+ getHistory(filter = {}) {
486
+ let history = [...this.validationHistory];
487
+
488
+ if (filter.type) {
489
+ history = history.filter(h => h.type === filter.type);
490
+ }
491
+
492
+ if (filter.valid !== undefined) {
493
+ history = history.filter(h => h.valid === filter.valid);
494
+ }
495
+
496
+ if (filter.limit) {
497
+ history = history.slice(-filter.limit);
498
+ }
499
+
500
+ return history;
501
+ }
502
+
503
+ /**
504
+ * Export traceability matrix as markdown
505
+ * @returns {string}
506
+ */
507
+ exportMatrix() {
508
+ let md = `# Traceability Matrix\n\n`;
509
+ md += `Generated: ${new Date().toISOString()}\n\n`;
510
+
511
+ // Artifact summary
512
+ md += `## Artifacts\n\n`;
513
+ md += `| Type | Count |\n`;
514
+ md += `|------|-------|\n`;
515
+
516
+ const typeCounts = {};
517
+ for (const [, artifact] of this.artifacts) {
518
+ typeCounts[artifact.type] = (typeCounts[artifact.type] || 0) + 1;
519
+ }
520
+
521
+ for (const [type, count] of Object.entries(typeCounts)) {
522
+ md += `| ${type} | ${count} |\n`;
523
+ }
524
+
525
+ md += `\n## Links\n\n`;
526
+ md += `| Source | Link Type | Target |\n`;
527
+ md += `|--------|-----------|--------|\n`;
528
+
529
+ for (const [sourceId, links] of this.traceabilityMatrix) {
530
+ for (const link of links) {
531
+ md += `| ${sourceId} | ${link.type} | ${link.target} |\n`;
532
+ }
533
+ }
534
+
535
+ md += `\n---\n`;
536
+ md += `Coverage: ${this.calculateCoverage()}%\n`;
537
+ md += `Total Links: ${this.countLinks()}\n`;
538
+
539
+ return md;
540
+ }
541
+
542
+ /**
543
+ * Get stats
544
+ * @returns {Object}
545
+ */
546
+ getStats() {
547
+ return {
548
+ artifactCount: this.artifacts.size,
549
+ linkCount: this.countLinks(),
550
+ ruleCount: this.customRules.size,
551
+ historyCount: this.validationHistory.length,
552
+ coverage: this.calculateCoverage()
553
+ };
554
+ }
555
+
556
+ /**
557
+ * Clear all data
558
+ */
559
+ clear() {
560
+ this.artifacts.clear();
561
+ this.traceabilityMatrix.clear();
562
+ this.validationHistory = [];
563
+ this.emit('cleared');
564
+ }
565
+ }
566
+
567
+ /**
568
+ * Factory function
569
+ */
570
+ function createAdvancedValidation(options = {}) {
571
+ return new AdvancedValidation(options);
572
+ }
573
+
574
+ module.exports = {
575
+ AdvancedValidation,
576
+ createAdvancedValidation,
577
+ VALIDATION_TYPE,
578
+ ARTIFACT_TYPE,
579
+ GAP_SEVERITY
580
+ };