musubi-sdd 6.1.1 → 6.2.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.
- package/package.json +1 -1
- package/src/orchestration/builtin-skills.js +425 -0
- package/src/templates/agents/claude-code/skills/design-reviewer/SKILL.md +1135 -0
- package/src/templates/agents/claude-code/skills/requirements-reviewer/SKILL.md +997 -0
- package/src/validators/design-reviewer.js +1300 -0
- package/src/validators/requirements-reviewer.js +1019 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "musubi-sdd",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.2.0",
|
|
4
4
|
"description": "Ultimate Specification Driven Development Tool with 27 Agents for 7 AI Coding Platforms + MCP Integration (Claude Code, GitHub Copilot, Cursor, Gemini CLI, Windsurf, Codex, Qwen Code)",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -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,
|