musubi-sdd 6.1.2 → 6.2.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.
@@ -14,6 +14,12 @@ const { WorkflowModeManager } = require('../managers/workflow-mode-manager');
14
14
  const { PackageManager } = require('../managers/package-manager');
15
15
  const { ConstitutionLevelManager } = require('../validators/constitution-level-manager');
16
16
  const { ProjectValidator } = require('../validators/project-validator');
17
+ const {
18
+ RequirementsReviewer,
19
+ ReviewMethod,
20
+ ReviewPerspective,
21
+ } = require('../validators/requirements-reviewer');
22
+ const { DesignReviewer, ReviewFocus, IssueSeverity } = require('../validators/design-reviewer');
17
23
  const { SkillCategory } = require('./skill-registry');
18
24
 
19
25
  /**
@@ -277,6 +283,419 @@ const projectConfigSkill = {
277
283
  },
278
284
  };
279
285
 
286
+ /**
287
+ * Requirements Reviewer Skill - Review requirements using Fagan Inspection and PBR
288
+ */
289
+ const requirementsReviewerSkill = {
290
+ id: 'requirements-reviewer',
291
+ name: 'Requirements Reviewer',
292
+ description:
293
+ 'Review requirements documents using Fagan Inspection and Perspective-Based Reading (PBR) techniques',
294
+ version: '1.0.0',
295
+ category: SkillCategory.VALIDATION,
296
+ tags: [
297
+ 'requirements',
298
+ 'review',
299
+ 'fagan',
300
+ 'inspection',
301
+ 'pbr',
302
+ 'perspective',
303
+ 'validation',
304
+ 'quality',
305
+ 'defect',
306
+ 'SRS',
307
+ ],
308
+ inputs: [
309
+ { name: 'action', type: 'string', description: 'review|fagan|pbr|metrics', required: true },
310
+ {
311
+ name: 'documentPath',
312
+ type: 'string',
313
+ description: 'Path to the requirements document',
314
+ required: true,
315
+ },
316
+ {
317
+ name: 'method',
318
+ type: 'string',
319
+ description: 'Review method: fagan, pbr, combined',
320
+ required: false,
321
+ },
322
+ {
323
+ name: 'perspectives',
324
+ type: 'array',
325
+ description: 'Perspectives for PBR: user, developer, tester, architect, security',
326
+ required: false,
327
+ },
328
+ { name: 'outputFormat', type: 'string', description: 'json, markdown', required: false },
329
+ { name: 'projectPath', type: 'string', description: 'Project root path', required: false },
330
+ ],
331
+ outputs: [
332
+ { name: 'defects', type: 'array', description: 'List of found defects' },
333
+ { name: 'metrics', type: 'object', description: 'Review metrics' },
334
+ { name: 'qualityGate', type: 'object', description: 'Quality gate result' },
335
+ { name: 'report', type: 'string', description: 'Markdown report' },
336
+ ],
337
+ timeout: 60000,
338
+ priority: 'P1',
339
+
340
+ async execute(input = {}) {
341
+ const projectPath = input.projectPath || process.cwd();
342
+ const reviewer = new RequirementsReviewer(projectPath);
343
+
344
+ switch (input.action) {
345
+ case 'review': {
346
+ if (!input.documentPath) {
347
+ return { success: false, error: 'documentPath is required for review action' };
348
+ }
349
+
350
+ const method = input.method || ReviewMethod.COMBINED;
351
+ const perspectives = input.perspectives || Object.values(ReviewPerspective);
352
+
353
+ const result = await reviewer.review(input.documentPath, {
354
+ method,
355
+ perspectives,
356
+ });
357
+
358
+ const response = {
359
+ success: true,
360
+ defects: result.defects.map(d => d.toJSON()),
361
+ metrics: result.metrics,
362
+ qualityGate: result.qualityGate,
363
+ };
364
+
365
+ if (input.outputFormat === 'markdown') {
366
+ response.report = result.toMarkdown();
367
+ }
368
+
369
+ return response;
370
+ }
371
+
372
+ case 'fagan': {
373
+ if (!input.documentPath) {
374
+ return { success: false, error: 'documentPath is required for fagan action' };
375
+ }
376
+
377
+ const content = await reviewer.loadDocument(input.documentPath);
378
+ const result = await reviewer.reviewFagan(content);
379
+
380
+ return {
381
+ success: true,
382
+ defects: result.defects.map(d => d.toJSON()),
383
+ metrics: result.metrics,
384
+ qualityGate: result.qualityGate,
385
+ report: input.outputFormat === 'markdown' ? result.toMarkdown() : undefined,
386
+ };
387
+ }
388
+
389
+ case 'pbr': {
390
+ if (!input.documentPath) {
391
+ return { success: false, error: 'documentPath is required for pbr action' };
392
+ }
393
+
394
+ const perspectives = input.perspectives || Object.values(ReviewPerspective);
395
+ const content = await reviewer.loadDocument(input.documentPath);
396
+ const result = await reviewer.reviewPBR(content, { perspectives });
397
+
398
+ return {
399
+ success: true,
400
+ defects: result.defects.map(d => d.toJSON()),
401
+ metrics: result.metrics,
402
+ qualityGate: result.qualityGate,
403
+ report: input.outputFormat === 'markdown' ? result.toMarkdown() : undefined,
404
+ };
405
+ }
406
+
407
+ case 'metrics': {
408
+ if (!input.documentPath) {
409
+ return { success: false, error: 'documentPath is required for metrics action' };
410
+ }
411
+
412
+ const content = await reviewer.loadDocument(input.documentPath);
413
+ const requirements = reviewer.extractRequirements(content);
414
+
415
+ return {
416
+ success: true,
417
+ metrics: {
418
+ totalRequirements: requirements.length,
419
+ earsCompliance: reviewer.checkEarsCompliance(requirements),
420
+ testabilityScore: reviewer.checkTestability(requirements),
421
+ },
422
+ };
423
+ }
424
+
425
+ case 'correct': {
426
+ if (!input.documentPath) {
427
+ return { success: false, error: 'documentPath is required for correct action' };
428
+ }
429
+ if (!input.corrections || !Array.isArray(input.corrections)) {
430
+ return { success: false, error: 'corrections array is required for correct action' };
431
+ }
432
+
433
+ const result = await reviewer.applyCorrections(input.documentPath, input.corrections, {
434
+ createBackup: input.createBackup !== false,
435
+ updateJapanese: input.updateJapanese !== false,
436
+ reviewOptions: {
437
+ method: input.method || ReviewMethod.COMBINED,
438
+ },
439
+ });
440
+
441
+ const response = {
442
+ success: true,
443
+ changesApplied: result.changesApplied,
444
+ rejectedFindings: result.rejectedFindings,
445
+ updatedQualityGate: result.updatedQualityGate,
446
+ filesModified: result.filesModified,
447
+ };
448
+
449
+ if (input.outputFormat === 'markdown') {
450
+ response.report = reviewer.generateCorrectionReport(result);
451
+ }
452
+
453
+ return response;
454
+ }
455
+
456
+ default:
457
+ return {
458
+ success: false,
459
+ error: 'Invalid action. Use: review, fagan, pbr, metrics, correct',
460
+ };
461
+ }
462
+ },
463
+ };
464
+
465
+ /**
466
+ * Design Reviewer Skill - Review design documents using ATAM, SOLID, and other techniques
467
+ */
468
+ const designReviewerSkill = {
469
+ id: 'design-reviewer',
470
+ name: 'Design Reviewer',
471
+ description:
472
+ 'Review design documents using ATAM, SOLID principles, design patterns, coupling/cohesion analysis, error handling, and security review',
473
+ version: '1.0.0',
474
+ category: SkillCategory.VALIDATION,
475
+ tags: [
476
+ 'design',
477
+ 'review',
478
+ 'atam',
479
+ 'solid',
480
+ 'patterns',
481
+ 'coupling',
482
+ 'cohesion',
483
+ 'security',
484
+ 'architecture',
485
+ 'quality',
486
+ 'c4',
487
+ 'adr',
488
+ ],
489
+ inputs: [
490
+ {
491
+ name: 'action',
492
+ type: 'string',
493
+ description: 'review|solid|patterns|coupling|security|c4|adr',
494
+ required: true,
495
+ },
496
+ {
497
+ name: 'documentPath',
498
+ type: 'string',
499
+ description: 'Path to the design document',
500
+ required: true,
501
+ },
502
+ {
503
+ name: 'focus',
504
+ type: 'array',
505
+ description:
506
+ 'Review focus areas: solid, patterns, coupling-cohesion, error-handling, security, all',
507
+ required: false,
508
+ },
509
+ { name: 'outputFormat', type: 'string', description: 'json, markdown', required: false },
510
+ { name: 'projectPath', type: 'string', description: 'Project root path', required: false },
511
+ {
512
+ name: 'qualityGateOptions',
513
+ type: 'object',
514
+ description: 'Quality gate thresholds',
515
+ required: false,
516
+ },
517
+ ],
518
+ outputs: [
519
+ { name: 'issues', type: 'array', description: 'List of design issues' },
520
+ { name: 'metrics', type: 'object', description: 'Review metrics' },
521
+ { name: 'qualityGate', type: 'object', description: 'Quality gate result' },
522
+ { name: 'report', type: 'string', description: 'Markdown report' },
523
+ ],
524
+ timeout: 60000,
525
+ priority: 'P1',
526
+
527
+ async execute(input = {}) {
528
+ const projectPath = input.projectPath || process.cwd();
529
+ const reviewer = new DesignReviewer(projectPath);
530
+
531
+ switch (input.action) {
532
+ case 'review': {
533
+ if (!input.documentPath) {
534
+ return { success: false, error: 'documentPath is required for review action' };
535
+ }
536
+
537
+ const focus = input.focus || [ReviewFocus.ALL];
538
+
539
+ const result = await reviewer.review(input.documentPath, {
540
+ focus,
541
+ qualityGateOptions: input.qualityGateOptions,
542
+ });
543
+
544
+ const response = {
545
+ success: true,
546
+ issues: result.issues.map(i => i.toJSON()),
547
+ metrics: result.metrics,
548
+ qualityGate: result.qualityGate,
549
+ };
550
+
551
+ if (input.outputFormat === 'markdown') {
552
+ response.report = result.toMarkdown();
553
+ }
554
+
555
+ return response;
556
+ }
557
+
558
+ case 'solid': {
559
+ if (!input.documentPath) {
560
+ return { success: false, error: 'documentPath is required for solid action' };
561
+ }
562
+
563
+ const content = await reviewer.loadDocument(input.documentPath);
564
+ const issues = reviewer.reviewSOLID(content);
565
+
566
+ return {
567
+ success: true,
568
+ issues: issues.map(i => i.toJSON()),
569
+ count: issues.length,
570
+ severity: {
571
+ critical: issues.filter(i => i.severity === IssueSeverity.CRITICAL).length,
572
+ major: issues.filter(i => i.severity === IssueSeverity.MAJOR).length,
573
+ minor: issues.filter(i => i.severity === IssueSeverity.MINOR).length,
574
+ },
575
+ };
576
+ }
577
+
578
+ case 'patterns': {
579
+ if (!input.documentPath) {
580
+ return { success: false, error: 'documentPath is required for patterns action' };
581
+ }
582
+
583
+ const content = await reviewer.loadDocument(input.documentPath);
584
+ const issues = reviewer.reviewPatterns(content);
585
+
586
+ return {
587
+ success: true,
588
+ issues: issues.map(i => i.toJSON()),
589
+ count: issues.length,
590
+ };
591
+ }
592
+
593
+ case 'coupling': {
594
+ if (!input.documentPath) {
595
+ return { success: false, error: 'documentPath is required for coupling action' };
596
+ }
597
+
598
+ const content = await reviewer.loadDocument(input.documentPath);
599
+ const issues = reviewer.reviewCouplingCohesion(content);
600
+
601
+ return {
602
+ success: true,
603
+ issues: issues.map(i => i.toJSON()),
604
+ count: issues.length,
605
+ };
606
+ }
607
+
608
+ case 'security': {
609
+ if (!input.documentPath) {
610
+ return { success: false, error: 'documentPath is required for security action' };
611
+ }
612
+
613
+ const content = await reviewer.loadDocument(input.documentPath);
614
+ const issues = reviewer.reviewSecurity(content);
615
+
616
+ return {
617
+ success: true,
618
+ issues: issues.map(i => i.toJSON()),
619
+ count: issues.length,
620
+ critical: issues.filter(i => i.severity === IssueSeverity.CRITICAL).length,
621
+ };
622
+ }
623
+
624
+ case 'c4': {
625
+ if (!input.documentPath) {
626
+ return { success: false, error: 'documentPath is required for c4 action' };
627
+ }
628
+
629
+ const content = await reviewer.loadDocument(input.documentPath);
630
+ const issues = reviewer.reviewC4Model(content);
631
+
632
+ return {
633
+ success: true,
634
+ issues: issues.map(i => i.toJSON()),
635
+ count: issues.length,
636
+ };
637
+ }
638
+
639
+ case 'adr': {
640
+ if (!input.documentPath) {
641
+ return { success: false, error: 'documentPath is required for adr action' };
642
+ }
643
+
644
+ const content = await reviewer.loadDocument(input.documentPath);
645
+ const issues = reviewer.reviewADR(content);
646
+
647
+ return {
648
+ success: true,
649
+ issues: issues.map(i => i.toJSON()),
650
+ count: issues.length,
651
+ };
652
+ }
653
+
654
+ case 'correct': {
655
+ if (!input.documentPath) {
656
+ return { success: false, error: 'documentPath is required for correct action' };
657
+ }
658
+ if (!input.corrections || !Array.isArray(input.corrections)) {
659
+ return { success: false, error: 'corrections array is required for correct action' };
660
+ }
661
+
662
+ const result = await reviewer.applyCorrections(input.documentPath, input.corrections, {
663
+ createBackup: input.createBackup !== false,
664
+ updateJapanese: input.updateJapanese !== false,
665
+ generateADRs: input.generateADRs !== false,
666
+ adrPath: input.adrPath,
667
+ reviewOptions: {
668
+ focus: input.focus || [ReviewFocus.ALL],
669
+ },
670
+ });
671
+
672
+ const response = {
673
+ success: true,
674
+ changesApplied: result.changesApplied,
675
+ rejectedFindings: result.rejectedFindings,
676
+ adrsCreated: result.adrsCreated,
677
+ updatedQualityGate: result.updatedQualityGate,
678
+ updatedSolidCompliance: result.updatedSolidCompliance,
679
+ filesModified: result.filesModified,
680
+ };
681
+
682
+ if (input.outputFormat === 'markdown') {
683
+ response.report = reviewer.generateCorrectionReport(result);
684
+ }
685
+
686
+ return response;
687
+ }
688
+
689
+ default:
690
+ return {
691
+ success: false,
692
+ error:
693
+ 'Invalid action. Use: review, solid, patterns, coupling, security, c4, adr, correct',
694
+ };
695
+ }
696
+ },
697
+ };
698
+
280
699
  /**
281
700
  * Register all built-in skills to a registry
282
701
  * @param {SkillRegistry} registry - The skill registry
@@ -288,6 +707,8 @@ function registerBuiltInSkills(registry) {
288
707
  packageManagerSkill,
289
708
  constitutionLevelSkill,
290
709
  projectConfigSkill,
710
+ requirementsReviewerSkill,
711
+ designReviewerSkill,
291
712
  ];
292
713
 
293
714
  for (const skill of skills) {
@@ -311,6 +732,8 @@ function getBuiltInSkills() {
311
732
  packageManagerSkill,
312
733
  constitutionLevelSkill,
313
734
  projectConfigSkill,
735
+ requirementsReviewerSkill,
736
+ designReviewerSkill,
314
737
  ];
315
738
  }
316
739
 
@@ -321,6 +744,8 @@ module.exports = {
321
744
  packageManagerSkill,
322
745
  constitutionLevelSkill,
323
746
  projectConfigSkill,
747
+ requirementsReviewerSkill,
748
+ designReviewerSkill,
324
749
 
325
750
  // Utility functions
326
751
  registerBuiltInSkills,