musubi-sdd 5.1.0 β 5.6.2
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/README.ja.md +106 -48
- package/README.md +110 -32
- package/bin/musubi-analyze.js +74 -67
- package/bin/musubi-browser.js +27 -26
- package/bin/musubi-change.js +48 -47
- package/bin/musubi-checkpoint.js +10 -7
- package/bin/musubi-convert.js +25 -25
- package/bin/musubi-costs.js +27 -10
- package/bin/musubi-gui.js +52 -46
- package/bin/musubi-init.js +1952 -10
- package/bin/musubi-orchestrate.js +327 -239
- package/bin/musubi-remember.js +69 -56
- package/bin/musubi-resolve.js +53 -45
- package/bin/musubi-trace.js +51 -22
- package/bin/musubi-validate.js +39 -30
- package/bin/musubi-workflow.js +33 -34
- package/bin/musubi.js +39 -2
- package/package.json +1 -1
- package/src/agents/agent-loop.js +94 -95
- package/src/agents/agentic/code-generator.js +119 -109
- package/src/agents/agentic/code-reviewer.js +105 -108
- package/src/agents/agentic/index.js +4 -4
- package/src/agents/browser/action-executor.js +13 -13
- package/src/agents/browser/ai-comparator.js +11 -10
- package/src/agents/browser/context-manager.js +6 -6
- package/src/agents/browser/index.js +5 -5
- package/src/agents/browser/nl-parser.js +31 -46
- package/src/agents/browser/screenshot.js +2 -2
- package/src/agents/browser/test-generator.js +6 -4
- package/src/agents/function-tool.js +71 -65
- package/src/agents/index.js +7 -7
- package/src/agents/schema-generator.js +98 -94
- package/src/analyzers/ast-extractor.js +158 -146
- package/src/analyzers/codegraph-auto-update.js +858 -0
- package/src/analyzers/complexity-analyzer.js +536 -0
- package/src/analyzers/context-optimizer.js +241 -126
- package/src/analyzers/impact-analyzer.js +1 -1
- package/src/analyzers/large-project-analyzer.js +766 -0
- package/src/analyzers/repository-map.js +77 -81
- package/src/analyzers/security-analyzer.js +19 -11
- package/src/analyzers/stuck-detector.js +19 -17
- package/src/converters/index.js +78 -57
- package/src/converters/ir/types.js +12 -12
- package/src/converters/parsers/musubi-parser.js +134 -126
- package/src/converters/parsers/openapi-parser.js +70 -53
- package/src/converters/parsers/speckit-parser.js +239 -175
- package/src/converters/writers/musubi-writer.js +123 -118
- package/src/converters/writers/speckit-writer.js +124 -113
- package/src/generators/rust-migration-generator.js +512 -0
- package/src/gui/public/index.html +1365 -1211
- package/src/gui/server.js +41 -40
- package/src/gui/services/file-watcher.js +23 -8
- package/src/gui/services/project-scanner.js +26 -20
- package/src/gui/services/replanning-service.js +27 -23
- package/src/gui/services/traceability-service.js +8 -8
- package/src/gui/services/workflow-service.js +14 -7
- package/src/index.js +151 -0
- package/src/integrations/cicd.js +90 -104
- package/src/integrations/codegraph-mcp.js +643 -0
- package/src/integrations/documentation.js +142 -103
- package/src/integrations/examples.js +95 -80
- package/src/integrations/github-client.js +17 -17
- package/src/integrations/index.js +5 -5
- package/src/integrations/mcp/index.js +21 -21
- package/src/integrations/mcp/mcp-context-provider.js +76 -78
- package/src/integrations/mcp/mcp-discovery.js +74 -72
- package/src/integrations/mcp/mcp-tool-registry.js +99 -94
- package/src/integrations/mcp-connector.js +70 -66
- package/src/integrations/platforms.js +50 -49
- package/src/integrations/tool-discovery.js +37 -31
- package/src/llm-providers/anthropic-provider.js +11 -11
- package/src/llm-providers/base-provider.js +16 -18
- package/src/llm-providers/copilot-provider.js +22 -19
- package/src/llm-providers/index.js +26 -25
- package/src/llm-providers/ollama-provider.js +11 -11
- package/src/llm-providers/openai-provider.js +12 -12
- package/src/managers/agent-memory.js +36 -24
- package/src/managers/checkpoint-manager.js +4 -8
- package/src/managers/delta-spec.js +19 -19
- package/src/managers/index.js +13 -4
- package/src/managers/memory-condenser.js +35 -45
- package/src/managers/repo-skill-manager.js +57 -31
- package/src/managers/skill-loader.js +25 -22
- package/src/managers/skill-tools.js +36 -72
- package/src/managers/workflow.js +30 -22
- package/src/monitoring/cost-tracker.js +48 -46
- package/src/monitoring/incident-manager.js +116 -106
- package/src/monitoring/index.js +144 -134
- package/src/monitoring/observability.js +75 -62
- package/src/monitoring/quality-dashboard.js +45 -41
- package/src/monitoring/release-manager.js +63 -53
- package/src/orchestration/agent-skill-binding.js +39 -47
- package/src/orchestration/error-handler.js +65 -107
- package/src/orchestration/guardrails/base-guardrail.js +26 -24
- package/src/orchestration/guardrails/guardrail-rules.js +50 -64
- package/src/orchestration/guardrails/index.js +5 -5
- package/src/orchestration/guardrails/input-guardrail.js +58 -45
- package/src/orchestration/guardrails/output-guardrail.js +104 -81
- package/src/orchestration/guardrails/safety-check.js +79 -79
- package/src/orchestration/index.js +38 -55
- package/src/orchestration/mcp-tool-adapters.js +96 -99
- package/src/orchestration/orchestration-engine.js +21 -21
- package/src/orchestration/pattern-registry.js +60 -45
- package/src/orchestration/patterns/auto.js +34 -47
- package/src/orchestration/patterns/group-chat.js +59 -65
- package/src/orchestration/patterns/handoff.js +67 -65
- package/src/orchestration/patterns/human-in-loop.js +51 -72
- package/src/orchestration/patterns/nested.js +25 -40
- package/src/orchestration/patterns/sequential.js +35 -34
- package/src/orchestration/patterns/swarm.js +63 -56
- package/src/orchestration/patterns/triage.js +150 -109
- package/src/orchestration/reasoning/index.js +9 -9
- package/src/orchestration/reasoning/planning-engine.js +143 -140
- package/src/orchestration/reasoning/reasoning-engine.js +206 -144
- package/src/orchestration/reasoning/self-correction.js +121 -128
- package/src/orchestration/replanning/adaptive-goal-modifier.js +107 -112
- package/src/orchestration/replanning/alternative-generator.js +37 -42
- package/src/orchestration/replanning/config.js +63 -59
- package/src/orchestration/replanning/goal-progress-tracker.js +98 -100
- package/src/orchestration/replanning/index.js +24 -20
- package/src/orchestration/replanning/plan-evaluator.js +49 -50
- package/src/orchestration/replanning/plan-monitor.js +32 -28
- package/src/orchestration/replanning/proactive-path-optimizer.js +175 -178
- package/src/orchestration/replanning/replan-history.js +33 -26
- package/src/orchestration/replanning/replanning-engine.js +106 -108
- package/src/orchestration/skill-executor.js +107 -109
- package/src/orchestration/skill-registry.js +85 -89
- package/src/orchestration/workflow-examples.js +228 -231
- package/src/orchestration/workflow-executor.js +65 -68
- package/src/orchestration/workflow-orchestrator.js +72 -73
- package/src/phase4-integration.js +47 -40
- package/src/phase5-integration.js +89 -30
- package/src/reporters/coverage-report.js +82 -30
- package/src/reporters/hierarchical-reporter.js +498 -0
- package/src/reporters/traceability-matrix-report.js +29 -20
- package/src/resolvers/issue-resolver.js +43 -31
- package/src/steering/advanced-validation.js +133 -124
- package/src/steering/auto-updater.js +60 -73
- package/src/steering/index.js +6 -6
- package/src/steering/quality-metrics.js +41 -35
- package/src/steering/steering-auto-update.js +83 -86
- package/src/steering/steering-validator.js +98 -106
- package/src/steering/template-constraints.js +53 -54
- package/src/templates/agents/claude-code/CLAUDE.md +32 -32
- package/src/templates/agents/claude-code/skills/agent-assistant/SKILL.md +13 -5
- package/src/templates/agents/claude-code/skills/ai-ml-engineer/mlops-guide.md +23 -23
- package/src/templates/agents/claude-code/skills/ai-ml-engineer/model-card-template.md +60 -41
- package/src/templates/agents/claude-code/skills/api-designer/api-patterns.md +27 -19
- package/src/templates/agents/claude-code/skills/api-designer/openapi-template.md +11 -7
- package/src/templates/agents/claude-code/skills/bug-hunter/SKILL.md +4 -3
- package/src/templates/agents/claude-code/skills/bug-hunter/root-cause-analysis.md +37 -15
- package/src/templates/agents/claude-code/skills/change-impact-analyzer/dependency-graph-patterns.md +36 -42
- package/src/templates/agents/claude-code/skills/change-impact-analyzer/impact-analysis-template.md +69 -60
- package/src/templates/agents/claude-code/skills/cloud-architect/aws-patterns.md +31 -38
- package/src/templates/agents/claude-code/skills/cloud-architect/azure-patterns.md +28 -23
- package/src/templates/agents/claude-code/skills/code-reviewer/SKILL.md +61 -0
- package/src/templates/agents/claude-code/skills/code-reviewer/best-practices.md +27 -0
- package/src/templates/agents/claude-code/skills/code-reviewer/review-checklist.md +29 -10
- package/src/templates/agents/claude-code/skills/code-reviewer/review-standards.md +29 -24
- package/src/templates/agents/claude-code/skills/constitution-enforcer/SKILL.md +8 -6
- package/src/templates/agents/claude-code/skills/constitution-enforcer/constitutional-articles.md +62 -26
- package/src/templates/agents/claude-code/skills/constitution-enforcer/phase-minus-one-gates.md +35 -16
- package/src/templates/agents/claude-code/skills/database-administrator/backup-recovery.md +27 -17
- package/src/templates/agents/claude-code/skills/database-administrator/tuning-guide.md +25 -20
- package/src/templates/agents/claude-code/skills/database-schema-designer/schema-patterns.md +39 -22
- package/src/templates/agents/claude-code/skills/devops-engineer/ci-cd-templates.md +25 -22
- package/src/templates/agents/claude-code/skills/issue-resolver/SKILL.md +24 -21
- package/src/templates/agents/claude-code/skills/orchestrator/SKILL.md +148 -63
- package/src/templates/agents/claude-code/skills/orchestrator/patterns.md +35 -16
- package/src/templates/agents/claude-code/skills/orchestrator/selection-matrix.md +69 -64
- package/src/templates/agents/claude-code/skills/performance-engineer/optimization-playbook.md +47 -47
- package/src/templates/agents/claude-code/skills/performance-optimizer/SKILL.md +69 -0
- package/src/templates/agents/claude-code/skills/performance-optimizer/benchmark-template.md +63 -45
- package/src/templates/agents/claude-code/skills/performance-optimizer/optimization-patterns.md +33 -35
- package/src/templates/agents/claude-code/skills/project-manager/SKILL.md +7 -6
- package/src/templates/agents/claude-code/skills/project-manager/agile-ceremonies.md +47 -28
- package/src/templates/agents/claude-code/skills/project-manager/project-templates.md +94 -78
- package/src/templates/agents/claude-code/skills/quality-assurance/SKILL.md +20 -17
- package/src/templates/agents/claude-code/skills/quality-assurance/qa-plan-template.md +63 -49
- package/src/templates/agents/claude-code/skills/release-coordinator/SKILL.md +5 -5
- package/src/templates/agents/claude-code/skills/release-coordinator/feature-flag-guide.md +30 -26
- package/src/templates/agents/claude-code/skills/release-coordinator/release-plan-template.md +67 -35
- package/src/templates/agents/claude-code/skills/requirements-analyst/ears-format.md +54 -42
- package/src/templates/agents/claude-code/skills/requirements-analyst/validation-rules.md +36 -33
- package/src/templates/agents/claude-code/skills/security-auditor/SKILL.md +77 -19
- package/src/templates/agents/claude-code/skills/security-auditor/audit-checklists.md +24 -24
- package/src/templates/agents/claude-code/skills/security-auditor/owasp-top-10.md +61 -20
- package/src/templates/agents/claude-code/skills/security-auditor/vulnerability-patterns.md +43 -11
- package/src/templates/agents/claude-code/skills/site-reliability-engineer/SKILL.md +1 -0
- package/src/templates/agents/claude-code/skills/site-reliability-engineer/incident-response-template.md +55 -25
- package/src/templates/agents/claude-code/skills/site-reliability-engineer/observability-patterns.md +78 -68
- package/src/templates/agents/claude-code/skills/site-reliability-engineer/slo-sli-guide.md +73 -53
- package/src/templates/agents/claude-code/skills/software-developer/solid-principles.md +83 -37
- package/src/templates/agents/claude-code/skills/software-developer/test-first-workflow.md +38 -31
- package/src/templates/agents/claude-code/skills/steering/SKILL.md +1 -0
- package/src/templates/agents/claude-code/skills/steering/auto-update-rules.md +31 -0
- package/src/templates/agents/claude-code/skills/system-architect/adr-template.md +25 -7
- package/src/templates/agents/claude-code/skills/system-architect/c4-model-guide.md +74 -61
- package/src/templates/agents/claude-code/skills/technical-writer/doc-templates/documentation-templates.md +70 -52
- package/src/templates/agents/claude-code/skills/test-engineer/SKILL.md +2 -0
- package/src/templates/agents/claude-code/skills/test-engineer/ears-test-mapping.md +75 -71
- package/src/templates/agents/claude-code/skills/test-engineer/test-types.md +85 -63
- package/src/templates/agents/claude-code/skills/traceability-auditor/coverage-matrix-template.md +39 -36
- package/src/templates/agents/claude-code/skills/traceability-auditor/gap-detection-rules.md +22 -17
- package/src/templates/agents/claude-code/skills/ui-ux-designer/SKILL.md +1 -0
- package/src/templates/agents/claude-code/skills/ui-ux-designer/accessibility-guidelines.md +49 -75
- package/src/templates/agents/claude-code/skills/ui-ux-designer/design-system-components.md +71 -59
- package/src/templates/agents/codex/AGENTS.md +74 -42
- package/src/templates/agents/cursor/AGENTS.md +74 -42
- package/src/templates/agents/gemini-cli/GEMINI.md +74 -42
- package/src/templates/agents/github-copilot/AGENTS.md +83 -51
- package/src/templates/agents/qwen-code/QWEN.md +74 -42
- package/src/templates/agents/windsurf/AGENTS.md +74 -42
- package/src/templates/architectures/README.md +41 -0
- package/src/templates/architectures/clean-architecture/README.md +113 -0
- package/src/templates/architectures/event-driven/README.md +162 -0
- package/src/templates/architectures/hexagonal/README.md +130 -0
- package/src/templates/index.js +6 -1
- package/src/templates/locale-manager.js +16 -16
- package/src/templates/shared/delta-spec-template.md +20 -13
- package/src/templates/shared/github-actions/musubi-issue-resolver.yml +5 -5
- package/src/templates/shared/github-actions/musubi-security-check.yml +3 -3
- package/src/templates/shared/github-actions/musubi-validate.yml +4 -4
- package/src/templates/shared/steering/structure.md +95 -0
- package/src/templates/skills/browser-agent.md +21 -16
- package/src/templates/skills/web-gui.md +8 -0
- package/src/templates/template-constraints.js +50 -53
- package/src/validators/advanced-validation.js +30 -36
- package/src/validators/constitutional-validator.js +77 -73
- package/src/validators/critic-system.js +49 -59
- package/src/validators/delta-format.js +59 -55
- package/src/validators/traceability-validator.js +7 -11
package/bin/musubi-analyze.js
CHANGED
|
@@ -62,7 +62,11 @@ program
|
|
|
62
62
|
.name('musubi-analyze')
|
|
63
63
|
.description('Analyze codebase for quality, complexity, and technical debt')
|
|
64
64
|
.version('3.6.1')
|
|
65
|
-
.option(
|
|
65
|
+
.option(
|
|
66
|
+
'-t, --type <type>',
|
|
67
|
+
'Analysis type: quality, dependencies, security, stuck, codegraph, all',
|
|
68
|
+
'all'
|
|
69
|
+
)
|
|
66
70
|
.option('-o, --output <file>', 'Output file for analysis report')
|
|
67
71
|
.option('--json', 'Output in JSON format')
|
|
68
72
|
.option('--threshold <level>', 'Quality threshold: low, medium, high', 'medium')
|
|
@@ -438,29 +442,29 @@ async function runCodeGraphIndex(full = false) {
|
|
|
438
442
|
if (full) {
|
|
439
443
|
args.push('--full');
|
|
440
444
|
}
|
|
441
|
-
|
|
445
|
+
|
|
442
446
|
log(`Running CodeGraph MCP index (${full ? 'full' : 'incremental'})...`, 'analyze');
|
|
443
|
-
|
|
447
|
+
|
|
444
448
|
const proc = spawn('codegraph-mcp', args, {
|
|
445
449
|
cwd: process.cwd(),
|
|
446
|
-
stdio: ['inherit', 'pipe', 'pipe']
|
|
450
|
+
stdio: ['inherit', 'pipe', 'pipe'],
|
|
447
451
|
});
|
|
448
|
-
|
|
452
|
+
|
|
449
453
|
let stdout = '';
|
|
450
454
|
let stderr = '';
|
|
451
|
-
|
|
452
|
-
proc.stdout.on('data',
|
|
455
|
+
|
|
456
|
+
proc.stdout.on('data', data => {
|
|
453
457
|
stdout += data.toString();
|
|
454
458
|
if (options.verbose) {
|
|
455
459
|
process.stdout.write(data);
|
|
456
460
|
}
|
|
457
461
|
});
|
|
458
|
-
|
|
459
|
-
proc.stderr.on('data',
|
|
462
|
+
|
|
463
|
+
proc.stderr.on('data', data => {
|
|
460
464
|
stderr += data.toString();
|
|
461
465
|
});
|
|
462
|
-
|
|
463
|
-
proc.on('close',
|
|
466
|
+
|
|
467
|
+
proc.on('close', code => {
|
|
464
468
|
if (code === 0) {
|
|
465
469
|
resolve({ success: true, output: stdout });
|
|
466
470
|
} else {
|
|
@@ -478,16 +482,16 @@ async function getCodeGraphStats() {
|
|
|
478
482
|
return new Promise((resolve, reject) => {
|
|
479
483
|
const proc = spawn('codegraph-mcp', ['stats', '.'], {
|
|
480
484
|
cwd: process.cwd(),
|
|
481
|
-
stdio: ['inherit', 'pipe', 'pipe']
|
|
485
|
+
stdio: ['inherit', 'pipe', 'pipe'],
|
|
482
486
|
});
|
|
483
|
-
|
|
487
|
+
|
|
484
488
|
let stdout = '';
|
|
485
|
-
|
|
486
|
-
proc.stdout.on('data',
|
|
489
|
+
|
|
490
|
+
proc.stdout.on('data', data => {
|
|
487
491
|
stdout += data.toString();
|
|
488
492
|
});
|
|
489
|
-
|
|
490
|
-
proc.on('close',
|
|
493
|
+
|
|
494
|
+
proc.on('close', code => {
|
|
491
495
|
if (code === 0) {
|
|
492
496
|
// Parse the stats output
|
|
493
497
|
const stats = parseCodeGraphStats(stdout);
|
|
@@ -510,12 +514,12 @@ function parseCodeGraphStats(output) {
|
|
|
510
514
|
relations: 0,
|
|
511
515
|
communities: 0,
|
|
512
516
|
files: 0,
|
|
513
|
-
entityTypes: {}
|
|
517
|
+
entityTypes: {},
|
|
514
518
|
};
|
|
515
|
-
|
|
519
|
+
|
|
516
520
|
const lines = output.split('\n');
|
|
517
521
|
let inEntityTypes = false;
|
|
518
|
-
|
|
522
|
+
|
|
519
523
|
for (const line of lines) {
|
|
520
524
|
if (line.startsWith('Entities:')) {
|
|
521
525
|
stats.entities = parseInt(line.split(':')[1].trim(), 10);
|
|
@@ -534,7 +538,7 @@ function parseCodeGraphStats(output) {
|
|
|
534
538
|
}
|
|
535
539
|
}
|
|
536
540
|
}
|
|
537
|
-
|
|
541
|
+
|
|
538
542
|
return stats;
|
|
539
543
|
}
|
|
540
544
|
|
|
@@ -546,7 +550,7 @@ async function generateCodeGraphReport(stats) {
|
|
|
546
550
|
const reportPath = 'steering/memories/codegraph.md';
|
|
547
551
|
const timestamp = new Date().toISOString();
|
|
548
552
|
const version = require('../package.json').version;
|
|
549
|
-
|
|
553
|
+
|
|
550
554
|
let report = `# CodeGraph MCP Index Report
|
|
551
555
|
|
|
552
556
|
**Generated**: ${timestamp}
|
|
@@ -602,9 +606,9 @@ codegraph-mcp serve --repo .
|
|
|
602
606
|
|
|
603
607
|
fs.ensureDirSync(path.dirname(reportPath));
|
|
604
608
|
fs.writeFileSync(reportPath, report);
|
|
605
|
-
|
|
609
|
+
|
|
606
610
|
log(`CodeGraph report saved to: ${reportPath}`, 'success');
|
|
607
|
-
|
|
611
|
+
|
|
608
612
|
return reportPath;
|
|
609
613
|
}
|
|
610
614
|
|
|
@@ -616,7 +620,7 @@ codegraph-mcp serve --repo .
|
|
|
616
620
|
async function analyzeCodeGraph(full = false) {
|
|
617
621
|
log('CodeGraph MCP Analysis', 'analyze');
|
|
618
622
|
console.log();
|
|
619
|
-
|
|
623
|
+
|
|
620
624
|
// Check if CodeGraph MCP is installed
|
|
621
625
|
if (!isCodeGraphInstalled()) {
|
|
622
626
|
log('CodeGraph MCP is not installed. Install with:', 'warning');
|
|
@@ -624,15 +628,15 @@ async function analyzeCodeGraph(full = false) {
|
|
|
624
628
|
console.log();
|
|
625
629
|
return null;
|
|
626
630
|
}
|
|
627
|
-
|
|
631
|
+
|
|
628
632
|
try {
|
|
629
633
|
// Run index
|
|
630
634
|
await runCodeGraphIndex(full);
|
|
631
635
|
console.log();
|
|
632
|
-
|
|
636
|
+
|
|
633
637
|
// Get statistics
|
|
634
638
|
const stats = await getCodeGraphStats();
|
|
635
|
-
|
|
639
|
+
|
|
636
640
|
// Display stats
|
|
637
641
|
console.log(chalk.bold('CodeGraph Statistics:'));
|
|
638
642
|
console.log(` Entities: ${chalk.green(stats.entities.toLocaleString())}`);
|
|
@@ -640,7 +644,7 @@ async function analyzeCodeGraph(full = false) {
|
|
|
640
644
|
console.log(` Communities: ${chalk.green(stats.communities)}`);
|
|
641
645
|
console.log(` Files: ${chalk.green(stats.files.toLocaleString())}`);
|
|
642
646
|
console.log();
|
|
643
|
-
|
|
647
|
+
|
|
644
648
|
if (Object.keys(stats.entityTypes).length > 0) {
|
|
645
649
|
console.log(chalk.bold('Entity Types:'));
|
|
646
650
|
for (const [type, count] of Object.entries(stats.entityTypes)) {
|
|
@@ -648,10 +652,10 @@ async function analyzeCodeGraph(full = false) {
|
|
|
648
652
|
}
|
|
649
653
|
console.log();
|
|
650
654
|
}
|
|
651
|
-
|
|
655
|
+
|
|
652
656
|
// Generate report
|
|
653
657
|
await generateCodeGraphReport(stats);
|
|
654
|
-
|
|
658
|
+
|
|
655
659
|
return stats;
|
|
656
660
|
} catch (error) {
|
|
657
661
|
log(`CodeGraph analysis failed: ${error.message}`, 'error');
|
|
@@ -671,51 +675,51 @@ async function analyzeStuckPatterns() {
|
|
|
671
675
|
isStuck: false,
|
|
672
676
|
confidence: 0,
|
|
673
677
|
patterns: [],
|
|
674
|
-
suggestions: []
|
|
678
|
+
suggestions: [],
|
|
675
679
|
};
|
|
676
680
|
|
|
677
681
|
try {
|
|
678
682
|
// Check git log for repetitive patterns
|
|
679
683
|
const { execSync } = require('child_process');
|
|
680
|
-
|
|
684
|
+
|
|
681
685
|
// Get recent commits
|
|
682
686
|
let commits = [];
|
|
683
687
|
try {
|
|
684
|
-
const gitLog = execSync(
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
688
|
+
const gitLog = execSync('git log --oneline -20 --format="%h|%s" 2>/dev/null', {
|
|
689
|
+
encoding: 'utf8',
|
|
690
|
+
}).trim();
|
|
691
|
+
commits = gitLog
|
|
692
|
+
.split('\n')
|
|
693
|
+
.filter(Boolean)
|
|
694
|
+
.map(line => {
|
|
695
|
+
const [hash, ...msgParts] = line.split('|');
|
|
696
|
+
return { hash, message: msgParts.join('|') };
|
|
697
|
+
});
|
|
692
698
|
} catch {
|
|
693
699
|
// Not in git repo or no commits
|
|
694
700
|
}
|
|
695
701
|
|
|
696
702
|
// Pattern 1: Repetitive revert/fix cycles
|
|
697
|
-
const revertPattern = commits.filter(
|
|
698
|
-
c.message.toLowerCase().includes('revert') ||
|
|
699
|
-
c.message.toLowerCase().includes('undo')
|
|
703
|
+
const revertPattern = commits.filter(
|
|
704
|
+
c => c.message.toLowerCase().includes('revert') || c.message.toLowerCase().includes('undo')
|
|
700
705
|
);
|
|
701
706
|
if (revertPattern.length >= 3) {
|
|
702
707
|
stuckPatterns.patterns.push({
|
|
703
708
|
type: 'revert-cycle',
|
|
704
709
|
severity: 'high',
|
|
705
710
|
message: `${revertPattern.length} revert commits detected in recent history`,
|
|
706
|
-
commits: revertPattern.slice(0, 3).map(c => c.message)
|
|
711
|
+
commits: revertPattern.slice(0, 3).map(c => c.message),
|
|
707
712
|
});
|
|
708
713
|
stuckPatterns.confidence += 30;
|
|
709
714
|
}
|
|
710
715
|
|
|
711
716
|
// Pattern 2: Same file edited repeatedly
|
|
712
|
-
let
|
|
717
|
+
let _recentChanges = [];
|
|
713
718
|
try {
|
|
714
|
-
const gitDiff = execSync(
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
).
|
|
718
|
-
recentChanges = gitDiff.split('\n').filter(Boolean);
|
|
719
|
+
const gitDiff = execSync('git diff --stat HEAD~5 HEAD 2>/dev/null', {
|
|
720
|
+
encoding: 'utf8',
|
|
721
|
+
}).trim();
|
|
722
|
+
_recentChanges = gitDiff.split('\n').filter(Boolean);
|
|
719
723
|
} catch {
|
|
720
724
|
// No recent changes or not enough history
|
|
721
725
|
}
|
|
@@ -723,10 +727,12 @@ async function analyzeStuckPatterns() {
|
|
|
723
727
|
const fileEditCounts = {};
|
|
724
728
|
for (let i = 0; i < Math.min(commits.length, 10); i++) {
|
|
725
729
|
try {
|
|
726
|
-
const files = execSync(
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
+
const files = execSync(`git show --name-only --format= ${commits[i].hash} 2>/dev/null`, {
|
|
731
|
+
encoding: 'utf8',
|
|
732
|
+
})
|
|
733
|
+
.trim()
|
|
734
|
+
.split('\n')
|
|
735
|
+
.filter(Boolean);
|
|
730
736
|
files.forEach(f => {
|
|
731
737
|
fileEditCounts[f] = (fileEditCounts[f] || 0) + 1;
|
|
732
738
|
});
|
|
@@ -744,7 +750,7 @@ async function analyzeStuckPatterns() {
|
|
|
744
750
|
type: 'circular-edit',
|
|
745
751
|
severity: 'medium',
|
|
746
752
|
message: 'Files being edited repeatedly without resolution',
|
|
747
|
-
files: frequentlyEdited
|
|
753
|
+
files: frequentlyEdited,
|
|
748
754
|
});
|
|
749
755
|
stuckPatterns.confidence += 25;
|
|
750
756
|
}
|
|
@@ -759,7 +765,7 @@ async function analyzeStuckPatterns() {
|
|
|
759
765
|
type: 'test-failure',
|
|
760
766
|
severity: 'medium',
|
|
761
767
|
message: `${testResults.numFailedTests} tests failing`,
|
|
762
|
-
failedTests: testResults.testResults?.filter(t => t.status === 'failed').slice(0, 5)
|
|
768
|
+
failedTests: testResults.testResults?.filter(t => t.status === 'failed').slice(0, 5),
|
|
763
769
|
});
|
|
764
770
|
stuckPatterns.confidence += 20;
|
|
765
771
|
}
|
|
@@ -792,7 +798,7 @@ async function analyzeStuckPatterns() {
|
|
|
792
798
|
type: 'repetitive-error',
|
|
793
799
|
severity: 'high',
|
|
794
800
|
message: 'Same errors occurring repeatedly',
|
|
795
|
-
errors: repetitiveErrors
|
|
801
|
+
errors: repetitiveErrors,
|
|
796
802
|
});
|
|
797
803
|
stuckPatterns.confidence += 30;
|
|
798
804
|
}
|
|
@@ -835,11 +841,12 @@ async function analyzeStuckPatterns() {
|
|
|
835
841
|
console.log(chalk.dim(`Confidence: ${stuckPatterns.confidence}%\n`));
|
|
836
842
|
|
|
837
843
|
stuckPatterns.patterns.forEach(pattern => {
|
|
838
|
-
const severityColor =
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
844
|
+
const severityColor =
|
|
845
|
+
{
|
|
846
|
+
high: chalk.red,
|
|
847
|
+
medium: chalk.yellow,
|
|
848
|
+
low: chalk.blue,
|
|
849
|
+
}[pattern.severity] || chalk.white;
|
|
843
850
|
|
|
844
851
|
console.log(severityColor(`[${pattern.severity.toUpperCase()}] ${pattern.type}`));
|
|
845
852
|
console.log(chalk.dim(` ${pattern.message}`));
|
|
@@ -876,11 +883,11 @@ async function main() {
|
|
|
876
883
|
// Handle --codegraph or --codegraph-full options
|
|
877
884
|
if (options.codegraph || options.codegraphFull || options.type === 'codegraph') {
|
|
878
885
|
analysisData.codegraph = await analyzeCodeGraph(options.codegraphFull);
|
|
879
|
-
|
|
886
|
+
|
|
880
887
|
if (options.json && analysisData.codegraph) {
|
|
881
888
|
console.log(JSON.stringify(analysisData.codegraph, null, 2));
|
|
882
889
|
}
|
|
883
|
-
|
|
890
|
+
|
|
884
891
|
if (options.type === 'codegraph') {
|
|
885
892
|
log('CodeGraph analysis complete!', 'success');
|
|
886
893
|
process.exit(0);
|
|
@@ -890,11 +897,11 @@ async function main() {
|
|
|
890
897
|
// Handle --detect-stuck option
|
|
891
898
|
if (options.detectStuck || options.type === 'stuck') {
|
|
892
899
|
analysisData.stuck = await analyzeStuckPatterns();
|
|
893
|
-
|
|
900
|
+
|
|
894
901
|
if (options.json) {
|
|
895
902
|
console.log(JSON.stringify(analysisData.stuck, null, 2));
|
|
896
903
|
}
|
|
897
|
-
|
|
904
|
+
|
|
898
905
|
if (options.type === 'stuck') {
|
|
899
906
|
process.exit(analysisData.stuck?.isStuck ? 1 : 0);
|
|
900
907
|
}
|
package/bin/musubi-browser.js
CHANGED
|
@@ -36,7 +36,7 @@ program
|
|
|
36
36
|
.option('-b, --browser <type>', 'Browser type (chromium/firefox/webkit)', 'chromium')
|
|
37
37
|
.option('-o, --output <dir>', 'Screenshot output directory', './screenshots')
|
|
38
38
|
.option('-t, --timeout <ms>', 'Default timeout in milliseconds', '30000')
|
|
39
|
-
.action(async
|
|
39
|
+
.action(async options => {
|
|
40
40
|
await runInteractive(options);
|
|
41
41
|
});
|
|
42
42
|
|
|
@@ -82,7 +82,7 @@ program
|
|
|
82
82
|
.option('-o, --output <file>', 'Output file path')
|
|
83
83
|
.option('-f, --format <format>', 'Test format (playwright/jest)', 'playwright')
|
|
84
84
|
.option('-H, --history <file>', 'Action history JSON file')
|
|
85
|
-
.action(async
|
|
85
|
+
.action(async options => {
|
|
86
86
|
await generateTest(options);
|
|
87
87
|
});
|
|
88
88
|
|
|
@@ -91,7 +91,7 @@ program
|
|
|
91
91
|
*/
|
|
92
92
|
async function runInteractive(options) {
|
|
93
93
|
const Agent = loadBrowserAgent();
|
|
94
|
-
|
|
94
|
+
|
|
95
95
|
console.log(chalk.cyan('\nπ MUSUBI Browser Agent - Interactive Mode'));
|
|
96
96
|
console.log(chalk.gray('Type browser commands in natural language. Type "help" for commands.\n'));
|
|
97
97
|
|
|
@@ -112,7 +112,7 @@ async function runInteractive(options) {
|
|
|
112
112
|
});
|
|
113
113
|
|
|
114
114
|
const prompt = () => {
|
|
115
|
-
rl.question(chalk.yellow('browser> '), async
|
|
115
|
+
rl.question(chalk.yellow('browser> '), async input => {
|
|
116
116
|
const command = input.trim();
|
|
117
117
|
|
|
118
118
|
if (!command) {
|
|
@@ -183,7 +183,6 @@ async function runInteractive(options) {
|
|
|
183
183
|
};
|
|
184
184
|
|
|
185
185
|
prompt();
|
|
186
|
-
|
|
187
186
|
} catch (error) {
|
|
188
187
|
console.error(chalk.red(`Error: ${error.message}`));
|
|
189
188
|
process.exit(1);
|
|
@@ -195,7 +194,7 @@ async function runInteractive(options) {
|
|
|
195
194
|
*/
|
|
196
195
|
async function runCommand(command, options) {
|
|
197
196
|
const Agent = loadBrowserAgent();
|
|
198
|
-
|
|
197
|
+
|
|
199
198
|
console.log(chalk.cyan('π MUSUBI Browser Agent'));
|
|
200
199
|
console.log(chalk.gray(`Command: ${command}\n`));
|
|
201
200
|
|
|
@@ -211,7 +210,7 @@ async function runCommand(command, options) {
|
|
|
211
210
|
|
|
212
211
|
if (result.success) {
|
|
213
212
|
console.log(chalk.green('β Command executed successfully'));
|
|
214
|
-
|
|
213
|
+
|
|
215
214
|
if (result.results) {
|
|
216
215
|
for (const r of result.results) {
|
|
217
216
|
console.log(chalk.gray(` ${r.type}: ${JSON.stringify(r.data)}`));
|
|
@@ -221,7 +220,6 @@ async function runCommand(command, options) {
|
|
|
221
220
|
console.log(chalk.red(`β Failed: ${result.error}`));
|
|
222
221
|
process.exitCode = 1;
|
|
223
222
|
}
|
|
224
|
-
|
|
225
223
|
} catch (error) {
|
|
226
224
|
console.error(chalk.red(`Error: ${error.message}`));
|
|
227
225
|
process.exitCode = 1;
|
|
@@ -235,8 +233,8 @@ async function runCommand(command, options) {
|
|
|
235
233
|
*/
|
|
236
234
|
async function runScript(file, options) {
|
|
237
235
|
const Agent = loadBrowserAgent();
|
|
238
|
-
|
|
239
|
-
if (!await fs.pathExists(file)) {
|
|
236
|
+
|
|
237
|
+
if (!(await fs.pathExists(file))) {
|
|
240
238
|
console.error(chalk.red(`Script file not found: ${file}`));
|
|
241
239
|
process.exit(1);
|
|
242
240
|
}
|
|
@@ -259,7 +257,7 @@ async function runScript(file, options) {
|
|
|
259
257
|
|
|
260
258
|
try {
|
|
261
259
|
await agent.launch();
|
|
262
|
-
|
|
260
|
+
|
|
263
261
|
let passed = 0;
|
|
264
262
|
let failed = 0;
|
|
265
263
|
|
|
@@ -290,7 +288,6 @@ async function runScript(file, options) {
|
|
|
290
288
|
if (failed > 0) {
|
|
291
289
|
process.exitCode = 1;
|
|
292
290
|
}
|
|
293
|
-
|
|
294
291
|
} catch (error) {
|
|
295
292
|
console.error(chalk.red(`Error: ${error.message}`));
|
|
296
293
|
process.exitCode = 1;
|
|
@@ -305,7 +302,7 @@ async function runScript(file, options) {
|
|
|
305
302
|
async function compareScreenshots(expected, actual, options) {
|
|
306
303
|
const Agent = loadBrowserAgent();
|
|
307
304
|
const { AIComparator } = Agent;
|
|
308
|
-
|
|
305
|
+
|
|
309
306
|
console.log(chalk.cyan('πΌοΈ Screenshot Comparison'));
|
|
310
307
|
console.log(chalk.gray(`Expected: ${expected}`));
|
|
311
308
|
console.log(chalk.gray(`Actual: ${actual}`));
|
|
@@ -323,15 +320,17 @@ async function compareScreenshots(expected, actual, options) {
|
|
|
323
320
|
if (result.passed) {
|
|
324
321
|
console.log(chalk.green(`β PASSED - Similarity: ${result.similarity}%`));
|
|
325
322
|
} else {
|
|
326
|
-
console.log(
|
|
327
|
-
|
|
323
|
+
console.log(
|
|
324
|
+
chalk.red(`β FAILED - Similarity: ${result.similarity}% (threshold: ${result.threshold}%)`)
|
|
325
|
+
);
|
|
326
|
+
|
|
328
327
|
if (result.differences.length > 0) {
|
|
329
328
|
console.log(chalk.yellow('\nDifferences:'));
|
|
330
329
|
for (const diff of result.differences) {
|
|
331
330
|
console.log(chalk.yellow(` - ${diff}`));
|
|
332
331
|
}
|
|
333
332
|
}
|
|
334
|
-
|
|
333
|
+
|
|
335
334
|
process.exitCode = 1;
|
|
336
335
|
}
|
|
337
336
|
|
|
@@ -340,7 +339,6 @@ async function compareScreenshots(expected, actual, options) {
|
|
|
340
339
|
const reportPath = path.join(path.dirname(actual), 'comparison-report.md');
|
|
341
340
|
await fs.writeFile(reportPath, report);
|
|
342
341
|
console.log(chalk.gray(`\nReport saved: ${reportPath}`));
|
|
343
|
-
|
|
344
342
|
} catch (error) {
|
|
345
343
|
console.error(chalk.red(`Error: ${error.message}`));
|
|
346
344
|
process.exitCode = 1;
|
|
@@ -353,14 +351,14 @@ async function compareScreenshots(expected, actual, options) {
|
|
|
353
351
|
async function generateTest(options) {
|
|
354
352
|
const Agent = loadBrowserAgent();
|
|
355
353
|
const { TestGenerator } = Agent;
|
|
356
|
-
|
|
354
|
+
|
|
357
355
|
console.log(chalk.cyan('π Generate Test Code'));
|
|
358
356
|
|
|
359
357
|
const generator = new TestGenerator();
|
|
360
|
-
|
|
358
|
+
|
|
361
359
|
let history = [];
|
|
362
360
|
if (options.history) {
|
|
363
|
-
if (!await fs.pathExists(options.history)) {
|
|
361
|
+
if (!(await fs.pathExists(options.history))) {
|
|
364
362
|
console.error(chalk.red(`History file not found: ${options.history}`));
|
|
365
363
|
process.exit(1);
|
|
366
364
|
}
|
|
@@ -379,7 +377,6 @@ async function generateTest(options) {
|
|
|
379
377
|
} else {
|
|
380
378
|
console.log('\n' + code);
|
|
381
379
|
}
|
|
382
|
-
|
|
383
380
|
} catch (error) {
|
|
384
381
|
console.error(chalk.red(`Error: ${error.message}`));
|
|
385
382
|
process.exitCode = 1;
|
|
@@ -396,7 +393,9 @@ function showHelp() {
|
|
|
396
393
|
console.log(chalk.gray(' Click:'));
|
|
397
394
|
console.log(' "γγ°γ€γ³γγΏγ³γγ―γͺγγ―" or "click login button"');
|
|
398
395
|
console.log(chalk.gray(' Fill:'));
|
|
399
|
-
console.log(
|
|
396
|
+
console.log(
|
|
397
|
+
' "γ‘γΌγ«ζ¬γ«γtest@example.comγγ¨ε
₯ε" or "type test@example.com in email field"'
|
|
398
|
+
);
|
|
400
399
|
console.log(chalk.gray(' Wait:'));
|
|
401
400
|
console.log(' "3η§εΎ
γ€" or "wait 3 seconds"');
|
|
402
401
|
console.log(chalk.gray(' Screenshot:'));
|
|
@@ -416,7 +415,7 @@ function showHelp() {
|
|
|
416
415
|
*/
|
|
417
416
|
function showHistory(agent) {
|
|
418
417
|
const history = agent.getActionHistory();
|
|
419
|
-
|
|
418
|
+
|
|
420
419
|
if (history.length === 0) {
|
|
421
420
|
console.log(chalk.gray('No actions in history.'));
|
|
422
421
|
return;
|
|
@@ -426,7 +425,9 @@ function showHistory(agent) {
|
|
|
426
425
|
for (let i = 0; i < history.length; i++) {
|
|
427
426
|
const item = history[i];
|
|
428
427
|
const status = item.result?.success ? chalk.green('β') : chalk.red('β');
|
|
429
|
-
console.log(
|
|
428
|
+
console.log(
|
|
429
|
+
` ${i + 1}. ${status} ${item.action.type}: ${item.action.raw || JSON.stringify(item.action)}`
|
|
430
|
+
);
|
|
430
431
|
}
|
|
431
432
|
console.log('');
|
|
432
433
|
}
|
|
@@ -436,14 +437,14 @@ function showHistory(agent) {
|
|
|
436
437
|
*/
|
|
437
438
|
async function saveTest(agent, outputPath) {
|
|
438
439
|
const history = agent.getActionHistory();
|
|
439
|
-
|
|
440
|
+
|
|
440
441
|
if (history.length === 0) {
|
|
441
442
|
console.log(chalk.yellow('No actions in history to save.'));
|
|
442
443
|
return;
|
|
443
444
|
}
|
|
444
445
|
|
|
445
446
|
try {
|
|
446
|
-
const
|
|
447
|
+
const _code = await agent.generateTest({
|
|
447
448
|
name: 'Interactive Session Test',
|
|
448
449
|
output: outputPath,
|
|
449
450
|
});
|