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,812 @@
1
+ /**
2
+ * Advanced Validation Module
3
+ *
4
+ * Provides:
5
+ * - Cross-artifact consistency validation
6
+ * - Gap detection between requirements and implementation
7
+ * - Completeness checks
8
+ * - Dependency validation
9
+ */
10
+
11
+ const EventEmitter = require('events');
12
+ const path = require('path');
13
+
14
+ // Validation Types
15
+ const ValidationType = {
16
+ CONSISTENCY: 'consistency',
17
+ COMPLETENESS: 'completeness',
18
+ GAP: 'gap',
19
+ DEPENDENCY: 'dependency',
20
+ REFERENCE: 'reference',
21
+ CUSTOM: 'custom'
22
+ };
23
+
24
+ // Severity Levels
25
+ const Severity = {
26
+ CRITICAL: 'critical',
27
+ ERROR: 'error',
28
+ WARNING: 'warning',
29
+ INFO: 'info'
30
+ };
31
+
32
+ // Artifact Types
33
+ const ArtifactType = {
34
+ REQUIREMENT: 'requirement',
35
+ DESIGN: 'design',
36
+ IMPLEMENTATION: 'implementation',
37
+ TEST: 'test',
38
+ DOCUMENTATION: 'documentation',
39
+ STEERING: 'steering'
40
+ };
41
+
42
+ /**
43
+ * Validation Issue
44
+ */
45
+ class ValidationIssue {
46
+ constructor(options = {}) {
47
+ this.id = options.id || `issue-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
48
+ this.type = options.type || ValidationType.CONSISTENCY;
49
+ this.severity = options.severity || Severity.ERROR;
50
+ this.message = options.message || 'Validation issue';
51
+ this.artifact = options.artifact || null;
52
+ this.location = options.location || null;
53
+ this.suggestion = options.suggestion || null;
54
+ this.relatedArtifacts = options.relatedArtifacts || [];
55
+ this.metadata = options.metadata || {};
56
+ this.timestamp = new Date();
57
+ }
58
+
59
+ toJSON() {
60
+ return {
61
+ id: this.id,
62
+ type: this.type,
63
+ severity: this.severity,
64
+ message: this.message,
65
+ artifact: this.artifact,
66
+ location: this.location,
67
+ suggestion: this.suggestion,
68
+ relatedArtifacts: this.relatedArtifacts,
69
+ timestamp: this.timestamp.toISOString()
70
+ };
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Artifact Reference
76
+ */
77
+ class ArtifactReference {
78
+ constructor(type, id, options = {}) {
79
+ this.type = type;
80
+ this.id = id;
81
+ this.name = options.name || id;
82
+ this.path = options.path || null;
83
+ this.version = options.version || null;
84
+ this.dependencies = options.dependencies || [];
85
+ this.references = options.references || [];
86
+ }
87
+
88
+ addDependency(ref) {
89
+ this.dependencies.push(ref);
90
+ return this;
91
+ }
92
+
93
+ addReference(ref) {
94
+ this.references.push(ref);
95
+ return this;
96
+ }
97
+
98
+ toJSON() {
99
+ return {
100
+ type: this.type,
101
+ id: this.id,
102
+ name: this.name,
103
+ path: this.path,
104
+ version: this.version,
105
+ dependencies: this.dependencies.map(d => typeof d === 'string' ? d : d.id),
106
+ references: this.references.map(r => typeof r === 'string' ? r : r.id)
107
+ };
108
+ }
109
+ }
110
+
111
+ /**
112
+ * Consistency Checker
113
+ */
114
+ class ConsistencyChecker {
115
+ constructor(options = {}) {
116
+ this.rules = [];
117
+ this.strictMode = options.strict || false;
118
+ }
119
+
120
+ addRule(rule) {
121
+ this.rules.push(rule);
122
+ return this;
123
+ }
124
+
125
+ check(artifacts) {
126
+ const issues = [];
127
+
128
+ for (const rule of this.rules) {
129
+ try {
130
+ const ruleIssues = rule.check(artifacts);
131
+ issues.push(...ruleIssues);
132
+ } catch (error) {
133
+ issues.push(new ValidationIssue({
134
+ type: ValidationType.CONSISTENCY,
135
+ severity: Severity.ERROR,
136
+ message: `Rule check failed: ${error.message}`,
137
+ metadata: { rule: rule.name, error: error.message }
138
+ }));
139
+ }
140
+ }
141
+
142
+ return {
143
+ valid: !issues.some(i => i.severity === Severity.CRITICAL || i.severity === Severity.ERROR),
144
+ issues,
145
+ rulesChecked: this.rules.length
146
+ };
147
+ }
148
+
149
+ // Built-in rules
150
+ static createNamingConsistencyRule() {
151
+ return {
152
+ name: 'naming-consistency',
153
+ check: (artifacts) => {
154
+ const issues = [];
155
+ const names = new Map();
156
+
157
+ for (const artifact of artifacts) {
158
+ const normalized = artifact.name?.toLowerCase().replace(/[-_\s]/g, '');
159
+ if (normalized && names.has(normalized)) {
160
+ const existing = names.get(normalized);
161
+ issues.push(new ValidationIssue({
162
+ type: ValidationType.CONSISTENCY,
163
+ severity: Severity.WARNING,
164
+ message: `Similar names detected: "${artifact.name}" and "${existing.name}"`,
165
+ artifact: artifact.id,
166
+ relatedArtifacts: [existing.id]
167
+ }));
168
+ }
169
+ if (normalized) {
170
+ names.set(normalized, artifact);
171
+ }
172
+ }
173
+
174
+ return issues;
175
+ }
176
+ };
177
+ }
178
+
179
+ static createVersionConsistencyRule() {
180
+ return {
181
+ name: 'version-consistency',
182
+ check: (artifacts) => {
183
+ const issues = [];
184
+ const versions = new Map();
185
+
186
+ for (const artifact of artifacts) {
187
+ if (artifact.version) {
188
+ if (!versions.has(artifact.type)) {
189
+ versions.set(artifact.type, []);
190
+ }
191
+ versions.get(artifact.type).push(artifact);
192
+ }
193
+ }
194
+
195
+ for (const [type, typeArtifacts] of versions) {
196
+ const uniqueVersions = new Set(typeArtifacts.map(a => a.version));
197
+ if (uniqueVersions.size > 1) {
198
+ issues.push(new ValidationIssue({
199
+ type: ValidationType.CONSISTENCY,
200
+ severity: Severity.WARNING,
201
+ message: `Multiple versions found for ${type}: ${[...uniqueVersions].join(', ')}`,
202
+ metadata: { type, versions: [...uniqueVersions] }
203
+ }));
204
+ }
205
+ }
206
+
207
+ return issues;
208
+ }
209
+ };
210
+ }
211
+ }
212
+
213
+ /**
214
+ * Gap Detector
215
+ */
216
+ class GapDetector {
217
+ constructor(options = {}) {
218
+ this.traceabilityMatrix = new Map();
219
+ this.requiredLinks = options.requiredLinks || {
220
+ [ArtifactType.REQUIREMENT]: [ArtifactType.DESIGN, ArtifactType.TEST],
221
+ [ArtifactType.DESIGN]: [ArtifactType.IMPLEMENTATION],
222
+ [ArtifactType.IMPLEMENTATION]: [ArtifactType.TEST]
223
+ };
224
+ }
225
+
226
+ addLink(source, target) {
227
+ if (!this.traceabilityMatrix.has(source)) {
228
+ this.traceabilityMatrix.set(source, new Set());
229
+ }
230
+ this.traceabilityMatrix.get(source).add(target);
231
+ return this;
232
+ }
233
+
234
+ detectGaps(artifacts) {
235
+ const issues = [];
236
+ const artifactMap = new Map(artifacts.map(a => [a.id, a]));
237
+
238
+ for (const artifact of artifacts) {
239
+ const requiredTargets = this.requiredLinks[artifact.type] || [];
240
+ const actualLinks = this.traceabilityMatrix.get(artifact.id) || new Set();
241
+
242
+ for (const requiredType of requiredTargets) {
243
+ const hasLink = [...actualLinks].some(linkId => {
244
+ const linked = artifactMap.get(linkId);
245
+ return linked && linked.type === requiredType;
246
+ });
247
+
248
+ if (!hasLink) {
249
+ issues.push(new ValidationIssue({
250
+ type: ValidationType.GAP,
251
+ severity: Severity.WARNING,
252
+ message: `${artifact.type} "${artifact.name}" has no linked ${requiredType}`,
253
+ artifact: artifact.id,
254
+ suggestion: `Create or link a ${requiredType} for this ${artifact.type}`
255
+ }));
256
+ }
257
+ }
258
+ }
259
+
260
+ return {
261
+ gaps: issues,
262
+ coverage: this.calculateCoverage(artifacts, issues)
263
+ };
264
+ }
265
+
266
+ calculateCoverage(artifacts, gaps) {
267
+ const totalRequired = artifacts.reduce((acc, a) => {
268
+ return acc + (this.requiredLinks[a.type]?.length || 0);
269
+ }, 0);
270
+
271
+ if (totalRequired === 0) return 100;
272
+
273
+ const gapCount = gaps.length;
274
+ return ((totalRequired - gapCount) / totalRequired) * 100;
275
+ }
276
+
277
+ getTraceabilityReport() {
278
+ const report = [];
279
+
280
+ for (const [source, targets] of this.traceabilityMatrix) {
281
+ report.push({
282
+ source,
283
+ targets: [...targets],
284
+ count: targets.size
285
+ });
286
+ }
287
+
288
+ return report;
289
+ }
290
+ }
291
+
292
+ /**
293
+ * Completeness Checker
294
+ */
295
+ class CompletenessChecker {
296
+ constructor(options = {}) {
297
+ this.requiredFields = options.requiredFields || {};
298
+ this.requiredSections = options.requiredSections || {};
299
+ }
300
+
301
+ setRequiredFields(type, fields) {
302
+ this.requiredFields[type] = fields;
303
+ return this;
304
+ }
305
+
306
+ setRequiredSections(type, sections) {
307
+ this.requiredSections[type] = sections;
308
+ return this;
309
+ }
310
+
311
+ checkArtifact(artifact) {
312
+ const issues = [];
313
+
314
+ // Check required fields
315
+ const requiredFields = this.requiredFields[artifact.type] || [];
316
+ for (const field of requiredFields) {
317
+ const value = artifact[field] || artifact.metadata?.[field];
318
+ if (value === undefined || value === null || value === '') {
319
+ issues.push(new ValidationIssue({
320
+ type: ValidationType.COMPLETENESS,
321
+ severity: Severity.ERROR,
322
+ message: `Missing required field "${field}" in ${artifact.type} "${artifact.name}"`,
323
+ artifact: artifact.id,
324
+ location: field
325
+ }));
326
+ }
327
+ }
328
+
329
+ // Check required sections (for document-like artifacts)
330
+ const requiredSections = this.requiredSections[artifact.type] || [];
331
+ const content = artifact.content || '';
332
+
333
+ for (const section of requiredSections) {
334
+ const sectionPattern = new RegExp(`^##?\\s+${section}`, 'im');
335
+ if (!sectionPattern.test(content)) {
336
+ issues.push(new ValidationIssue({
337
+ type: ValidationType.COMPLETENESS,
338
+ severity: Severity.WARNING,
339
+ message: `Missing section "${section}" in ${artifact.type} "${artifact.name}"`,
340
+ artifact: artifact.id,
341
+ suggestion: `Add a "## ${section}" section`
342
+ }));
343
+ }
344
+ }
345
+
346
+ return {
347
+ complete: issues.filter(i => i.severity === Severity.ERROR).length === 0,
348
+ issues,
349
+ artifact: artifact.id
350
+ };
351
+ }
352
+
353
+ checkAll(artifacts) {
354
+ const results = [];
355
+
356
+ for (const artifact of artifacts) {
357
+ results.push(this.checkArtifact(artifact));
358
+ }
359
+
360
+ const allIssues = results.flatMap(r => r.issues);
361
+ const completeCount = results.filter(r => r.complete).length;
362
+
363
+ return {
364
+ valid: allIssues.filter(i => i.severity === Severity.ERROR).length === 0,
365
+ completeness: (completeCount / artifacts.length) * 100,
366
+ results,
367
+ issues: allIssues
368
+ };
369
+ }
370
+ }
371
+
372
+ /**
373
+ * Dependency Validator
374
+ */
375
+ class DependencyValidator {
376
+ constructor(options = {}) {
377
+ this.dependencies = new Map();
378
+ this.allowCycles = options.allowCycles || false;
379
+ }
380
+
381
+ addDependency(from, to) {
382
+ if (!this.dependencies.has(from)) {
383
+ this.dependencies.set(from, new Set());
384
+ }
385
+ this.dependencies.get(from).add(to);
386
+ return this;
387
+ }
388
+
389
+ removeDependency(from, to) {
390
+ const deps = this.dependencies.get(from);
391
+ if (deps) {
392
+ deps.delete(to);
393
+ }
394
+ return this;
395
+ }
396
+
397
+ getDependencies(id) {
398
+ return [...(this.dependencies.get(id) || [])];
399
+ }
400
+
401
+ getDependents(id) {
402
+ const dependents = [];
403
+ for (const [from, tos] of this.dependencies) {
404
+ if (tos.has(id)) {
405
+ dependents.push(from);
406
+ }
407
+ }
408
+ return dependents;
409
+ }
410
+
411
+ detectCycles() {
412
+ const cycles = [];
413
+ const visited = new Set();
414
+ const stack = new Set();
415
+
416
+ const dfs = (node, path = []) => {
417
+ if (stack.has(node)) {
418
+ const cycleStart = path.indexOf(node);
419
+ cycles.push(path.slice(cycleStart).concat(node));
420
+ return;
421
+ }
422
+
423
+ if (visited.has(node)) return;
424
+
425
+ visited.add(node);
426
+ stack.add(node);
427
+ path.push(node);
428
+
429
+ const deps = this.dependencies.get(node) || new Set();
430
+ for (const dep of deps) {
431
+ dfs(dep, [...path]);
432
+ }
433
+
434
+ stack.delete(node);
435
+ };
436
+
437
+ for (const node of this.dependencies.keys()) {
438
+ dfs(node);
439
+ }
440
+
441
+ return cycles;
442
+ }
443
+
444
+ validate(artifacts) {
445
+ const issues = [];
446
+ const artifactIds = new Set(artifacts.map(a => a.id));
447
+
448
+ // Check for missing dependencies
449
+ for (const [from, tos] of this.dependencies) {
450
+ if (!artifactIds.has(from)) {
451
+ issues.push(new ValidationIssue({
452
+ type: ValidationType.DEPENDENCY,
453
+ severity: Severity.ERROR,
454
+ message: `Dependency source "${from}" not found in artifacts`,
455
+ artifact: from
456
+ }));
457
+ }
458
+
459
+ for (const to of tos) {
460
+ if (!artifactIds.has(to)) {
461
+ issues.push(new ValidationIssue({
462
+ type: ValidationType.DEPENDENCY,
463
+ severity: Severity.ERROR,
464
+ message: `Dependency target "${to}" not found (required by "${from}")`,
465
+ artifact: from,
466
+ relatedArtifacts: [to]
467
+ }));
468
+ }
469
+ }
470
+ }
471
+
472
+ // Check for cycles
473
+ if (!this.allowCycles) {
474
+ const cycles = this.detectCycles();
475
+ for (const cycle of cycles) {
476
+ issues.push(new ValidationIssue({
477
+ type: ValidationType.DEPENDENCY,
478
+ severity: Severity.ERROR,
479
+ message: `Circular dependency detected: ${cycle.join(' → ')}`,
480
+ metadata: { cycle }
481
+ }));
482
+ }
483
+ }
484
+
485
+ return {
486
+ valid: issues.length === 0,
487
+ issues,
488
+ cycles: this.detectCycles()
489
+ };
490
+ }
491
+
492
+ getTopologicalOrder() {
493
+ const sorted = [];
494
+ const visited = new Set();
495
+ const temp = new Set();
496
+
497
+ const visit = (node) => {
498
+ if (temp.has(node)) return false; // cycle
499
+ if (visited.has(node)) return true;
500
+
501
+ temp.add(node);
502
+ const deps = this.dependencies.get(node) || new Set();
503
+
504
+ for (const dep of deps) {
505
+ if (!visit(dep)) return false;
506
+ }
507
+
508
+ temp.delete(node);
509
+ visited.add(node);
510
+ sorted.unshift(node);
511
+ return true;
512
+ };
513
+
514
+ for (const node of this.dependencies.keys()) {
515
+ if (!visit(node)) return null; // cycle detected
516
+ }
517
+
518
+ return sorted;
519
+ }
520
+ }
521
+
522
+ /**
523
+ * Reference Validator
524
+ */
525
+ class ReferenceValidator {
526
+ constructor(options = {}) {
527
+ this.references = new Map();
528
+ this.patterns = options.patterns || {
529
+ requirement: /REQ-\d+/g,
530
+ design: /DES-\d+/g,
531
+ test: /TEST-\d+/g,
532
+ issue: /#\d+/g
533
+ };
534
+ }
535
+
536
+ registerReference(id, artifact) {
537
+ this.references.set(id, artifact);
538
+ return this;
539
+ }
540
+
541
+ extractReferences(content) {
542
+ const refs = [];
543
+
544
+ for (const [type, pattern] of Object.entries(this.patterns)) {
545
+ const matches = content.match(pattern) || [];
546
+ for (const match of matches) {
547
+ refs.push({ type, id: match });
548
+ }
549
+ }
550
+
551
+ return refs;
552
+ }
553
+
554
+ validate(artifacts) {
555
+ const issues = [];
556
+
557
+ for (const artifact of artifacts) {
558
+ const content = artifact.content || '';
559
+ const refs = this.extractReferences(content);
560
+
561
+ for (const ref of refs) {
562
+ if (!this.references.has(ref.id)) {
563
+ issues.push(new ValidationIssue({
564
+ type: ValidationType.REFERENCE,
565
+ severity: Severity.WARNING,
566
+ message: `Reference "${ref.id}" not found`,
567
+ artifact: artifact.id,
568
+ metadata: { referenceType: ref.type, referenceId: ref.id }
569
+ }));
570
+ }
571
+ }
572
+ }
573
+
574
+ return {
575
+ valid: issues.length === 0,
576
+ issues,
577
+ totalReferences: this.references.size
578
+ };
579
+ }
580
+ }
581
+
582
+ /**
583
+ * Advanced Validator (Main Class)
584
+ */
585
+ class AdvancedValidator extends EventEmitter {
586
+ constructor(options = {}) {
587
+ super();
588
+ this.consistencyChecker = new ConsistencyChecker(options.consistency);
589
+ this.gapDetector = new GapDetector(options.gaps);
590
+ this.completenessChecker = new CompletenessChecker(options.completeness);
591
+ this.dependencyValidator = new DependencyValidator(options.dependencies);
592
+ this.referenceValidator = new ReferenceValidator(options.references);
593
+ this.artifacts = new Map();
594
+ this.validationHistory = [];
595
+ }
596
+
597
+ // Artifact Management
598
+ registerArtifact(artifact) {
599
+ if (!(artifact instanceof ArtifactReference)) {
600
+ artifact = new ArtifactReference(
601
+ artifact.type,
602
+ artifact.id,
603
+ artifact
604
+ );
605
+ }
606
+ this.artifacts.set(artifact.id, artifact);
607
+ this.referenceValidator.registerReference(artifact.id, artifact);
608
+ this.emit('artifact:registered', artifact);
609
+ return this;
610
+ }
611
+
612
+ getArtifact(id) {
613
+ return this.artifacts.get(id);
614
+ }
615
+
616
+ getAllArtifacts() {
617
+ return [...this.artifacts.values()];
618
+ }
619
+
620
+ // Link Management
621
+ addLink(sourceId, targetId) {
622
+ this.gapDetector.addLink(sourceId, targetId);
623
+ this.dependencyValidator.addDependency(sourceId, targetId);
624
+ return this;
625
+ }
626
+
627
+ // Validation Methods
628
+ validateConsistency() {
629
+ const artifacts = this.getAllArtifacts();
630
+ const result = this.consistencyChecker.check(artifacts);
631
+ this.recordValidation('consistency', result);
632
+ return result;
633
+ }
634
+
635
+ validateGaps() {
636
+ const artifacts = this.getAllArtifacts();
637
+ const result = this.gapDetector.detectGaps(artifacts);
638
+ this.recordValidation('gaps', result);
639
+ return result;
640
+ }
641
+
642
+ validateCompleteness() {
643
+ const artifacts = this.getAllArtifacts();
644
+ const result = this.completenessChecker.checkAll(artifacts);
645
+ this.recordValidation('completeness', result);
646
+ return result;
647
+ }
648
+
649
+ validateDependencies() {
650
+ const artifacts = this.getAllArtifacts();
651
+ const result = this.dependencyValidator.validate(artifacts);
652
+ this.recordValidation('dependencies', result);
653
+ return result;
654
+ }
655
+
656
+ validateReferences() {
657
+ const artifacts = this.getAllArtifacts();
658
+ const result = this.referenceValidator.validate(artifacts);
659
+ this.recordValidation('references', result);
660
+ return result;
661
+ }
662
+
663
+ validateAll() {
664
+ const results = {
665
+ consistency: this.validateConsistency(),
666
+ gaps: this.validateGaps(),
667
+ completeness: this.validateCompleteness(),
668
+ dependencies: this.validateDependencies(),
669
+ references: this.validateReferences()
670
+ };
671
+
672
+ const allIssues = [
673
+ ...results.consistency.issues,
674
+ ...results.gaps.gaps,
675
+ ...results.completeness.issues,
676
+ ...results.dependencies.issues,
677
+ ...results.references.issues
678
+ ];
679
+
680
+ const valid = !allIssues.some(i =>
681
+ i.severity === Severity.CRITICAL || i.severity === Severity.ERROR
682
+ );
683
+
684
+ this.emit('validation:complete', { results, valid, issues: allIssues });
685
+
686
+ return {
687
+ valid,
688
+ results,
689
+ issues: allIssues,
690
+ summary: {
691
+ totalArtifacts: this.artifacts.size,
692
+ totalIssues: allIssues.length,
693
+ criticalIssues: allIssues.filter(i => i.severity === Severity.CRITICAL).length,
694
+ errorIssues: allIssues.filter(i => i.severity === Severity.ERROR).length,
695
+ warningIssues: allIssues.filter(i => i.severity === Severity.WARNING).length,
696
+ gapCoverage: results.gaps.coverage,
697
+ completeness: results.completeness.completeness
698
+ }
699
+ };
700
+ }
701
+
702
+ recordValidation(type, result) {
703
+ this.validationHistory.push({
704
+ type,
705
+ result,
706
+ timestamp: new Date()
707
+ });
708
+
709
+ // Keep last 100 validations
710
+ if (this.validationHistory.length > 100) {
711
+ this.validationHistory = this.validationHistory.slice(-100);
712
+ }
713
+ }
714
+
715
+ getValidationHistory(type = null) {
716
+ if (type) {
717
+ return this.validationHistory.filter(v => v.type === type);
718
+ }
719
+ return this.validationHistory;
720
+ }
721
+
722
+ // Report Generation
723
+ generateReport() {
724
+ const validation = this.validateAll();
725
+ const lines = [
726
+ '# Validation Report',
727
+ '',
728
+ `Generated: ${new Date().toISOString()}`,
729
+ '',
730
+ '## Summary',
731
+ '',
732
+ `- **Status**: ${validation.valid ? '✅ Valid' : '❌ Invalid'}`,
733
+ `- **Total Artifacts**: ${validation.summary.totalArtifacts}`,
734
+ `- **Total Issues**: ${validation.summary.totalIssues}`,
735
+ `- **Gap Coverage**: ${validation.summary.gapCoverage.toFixed(1)}%`,
736
+ `- **Completeness**: ${validation.summary.completeness.toFixed(1)}%`,
737
+ '',
738
+ '## Issues by Severity',
739
+ '',
740
+ `- Critical: ${validation.summary.criticalIssues}`,
741
+ `- Error: ${validation.summary.errorIssues}`,
742
+ `- Warning: ${validation.summary.warningIssues}`,
743
+ ''
744
+ ];
745
+
746
+ if (validation.issues.length > 0) {
747
+ lines.push('## Issues', '');
748
+
749
+ for (const issue of validation.issues) {
750
+ const icon = issue.severity === 'critical' ? '🔴' :
751
+ issue.severity === 'error' ? '🟠' : '🟡';
752
+ lines.push(`### ${icon} ${issue.message}`);
753
+ lines.push('');
754
+ lines.push(`- Type: ${issue.type}`);
755
+ lines.push(`- Severity: ${issue.severity}`);
756
+ if (issue.artifact) lines.push(`- Artifact: ${issue.artifact}`);
757
+ if (issue.suggestion) lines.push(`- Suggestion: ${issue.suggestion}`);
758
+ lines.push('');
759
+ }
760
+ }
761
+
762
+ return lines.join('\n');
763
+ }
764
+ }
765
+
766
+ /**
767
+ * Factory function
768
+ */
769
+ function createAdvancedValidator(options = {}) {
770
+ const validator = new AdvancedValidator(options);
771
+
772
+ // Add default consistency rules
773
+ validator.consistencyChecker.addRule(
774
+ ConsistencyChecker.createNamingConsistencyRule()
775
+ );
776
+ validator.consistencyChecker.addRule(
777
+ ConsistencyChecker.createVersionConsistencyRule()
778
+ );
779
+
780
+ // Set default completeness requirements
781
+ validator.completenessChecker.setRequiredFields(ArtifactType.REQUIREMENT, [
782
+ 'name', 'description'
783
+ ]);
784
+ validator.completenessChecker.setRequiredFields(ArtifactType.DESIGN, [
785
+ 'name', 'description'
786
+ ]);
787
+ validator.completenessChecker.setRequiredSections(ArtifactType.STEERING, [
788
+ 'Overview', 'Purpose'
789
+ ]);
790
+
791
+ return validator;
792
+ }
793
+
794
+ module.exports = {
795
+ // Constants
796
+ ValidationType,
797
+ Severity,
798
+ ArtifactType,
799
+
800
+ // Classes
801
+ ValidationIssue,
802
+ ArtifactReference,
803
+ ConsistencyChecker,
804
+ GapDetector,
805
+ CompletenessChecker,
806
+ DependencyValidator,
807
+ ReferenceValidator,
808
+ AdvancedValidator,
809
+
810
+ // Factory
811
+ createAdvancedValidator
812
+ };