musubi-sdd 2.1.1 → 2.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/README.ja.md +95 -10
- package/README.md +91 -10
- package/bin/musubi-analyze.js +219 -1
- package/bin/musubi-remember.js +342 -0
- package/bin/musubi-resolve.js +308 -0
- package/bin/musubi-validate.js +87 -0
- package/bin/musubi.js +4 -3
- package/package.json +7 -4
- package/src/analyzers/security-analyzer.js +676 -0
- package/src/analyzers/stuck-detector.js +484 -0
- package/src/integrations/github-client.js +292 -0
- package/src/managers/agent-memory.js +701 -0
- package/src/managers/memory-condenser.js +444 -0
- package/src/managers/repo-skill-manager.js +480 -0
- package/src/managers/skill-loader.js +425 -0
- package/src/resolvers/issue-resolver.js +703 -0
- package/src/templates/agents/claude-code/skills/agent-assistant/SKILL.md +221 -0
- package/src/templates/agents/claude-code/skills/bug-hunter/SKILL.md +61 -0
- package/src/templates/agents/claude-code/skills/issue-resolver/SKILL.md +251 -0
- package/src/templates/agents/claude-code/skills/orchestrator/SKILL.md +62 -0
- package/src/templates/agents/claude-code/skills/quality-assurance/SKILL.md +80 -0
- package/src/templates/agents/claude-code/skills/security-auditor/SKILL.md +68 -0
- package/src/templates/agents/codex/AGENTS.md +15 -0
- package/src/templates/agents/cursor/AGENTS.md +15 -0
- package/src/templates/agents/gemini-cli/GEMINI.md +15 -0
- package/src/templates/agents/github-copilot/AGENTS.md +30 -0
- package/src/templates/agents/qwen-code/QWEN.md +15 -0
- package/src/templates/agents/windsurf/AGENTS.md +15 -0
- package/src/templates/shared/github-actions/musubi-issue-resolver.yml +146 -0
- package/src/templates/shared/github-actions/musubi-security-check.yml +89 -0
- package/src/templates/shared/github-actions/musubi-validate.yml +107 -0
- package/src/validators/critic-system.js +657 -0
package/README.ja.md
CHANGED
|
@@ -1,10 +1,77 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# 🎋 MUSUBI
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**究極の仕様駆動開発ツール**
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
[](https://github.com/nahisaho/musubi/actions/workflows/ci.yml)
|
|
8
|
+
[](https://www.npmjs.com/package/musubi-sdd)
|
|
9
|
+
[](https://www.npmjs.com/package/musubi-sdd)
|
|
10
|
+
[](https://opensource.org/licenses/MIT)
|
|
11
|
+
[](https://nodejs.org)
|
|
12
|
+
[](http://makeapullrequest.com)
|
|
13
|
+
|
|
14
|
+
[English](README.md) | [日本語](README.ja.md) | [ドキュメント](docs/) | [npm](https://www.npmjs.com/package/musubi-sdd)
|
|
15
|
+
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
> 🤖 **7つのAIエージェント** × 📋 **25の専門スキル** × ⚖️ **憲法ガバナンス**
|
|
21
|
+
|
|
22
|
+
MUSUBI(結び)は、6つの主要フレームワークのベスト機能を統合した包括的な**仕様駆動開発(SDD)**フレームワークです。複数のAIコーディングエージェントに対応した本番環境対応ツールです。
|
|
23
|
+
|
|
24
|
+
<div align="center">
|
|
25
|
+
|
|
26
|
+

|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
## ✨ なぜMUSUBI?
|
|
31
|
+
|
|
32
|
+
| 課題 | MUSUBIのソリューション |
|
|
33
|
+
|------|----------------------|
|
|
34
|
+
| 🔀 AIツールの分断 | **7エージェント、1つの統一ワークフロー** |
|
|
35
|
+
| 📝 曖昧な要件定義 | **5パターンのEARS形式** |
|
|
36
|
+
| 🔍 トレーサビリティの喪失 | **100% 要件→設計→コード→テスト追跡** |
|
|
37
|
+
| ⚠️ 品質の不一致 | **9つの憲法条項 + フェーズ-1ゲート** |
|
|
38
|
+
| 🔄 既存プロジェクトの課題 | **差分仕様 + 変更管理** |
|
|
39
|
+
|
|
40
|
+
## 🚀 クイックスタート
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# 30秒でインストール&初期化
|
|
44
|
+
npx musubi-sdd init
|
|
45
|
+
|
|
46
|
+
# 既存プロジェクト向け - 自動分析とステアリングドキュメント生成
|
|
47
|
+
npx musubi-sdd onboard
|
|
48
|
+
|
|
49
|
+
# 完了!AIエージェントでSDDコマンドを使用:
|
|
50
|
+
# Claude Code: /sdd-requirements, /sdd-design, /sdd-implement
|
|
51
|
+
# GitHub Copilot: #sdd-requirements, #sdd-design, #sdd-implement
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
<details>
|
|
55
|
+
<summary>📦 その他のインストールオプション</summary>
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# グローバルインストール
|
|
59
|
+
npm install -g musubi-sdd
|
|
60
|
+
|
|
61
|
+
# 特定のAIエージェント向けに初期化
|
|
62
|
+
musubi init --copilot # GitHub Copilot
|
|
63
|
+
musubi init --cursor # Cursor IDE
|
|
64
|
+
musubi init --gemini # Gemini CLI
|
|
65
|
+
musubi init --codex # Codex CLI
|
|
66
|
+
musubi init --qwen # Qwen Code
|
|
67
|
+
musubi init --windsurf # Windsurf IDE
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
</details>
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 📊 v2.1.0 の新機能
|
|
8
75
|
|
|
9
76
|
- 🔄 **ワークフローエンジン** - ステージ管理とメトリクス収集の新CLI `musubi-workflow`
|
|
10
77
|
- 📊 **メトリクス収集** - ステージごとの所要時間、イテレーション回数、フィードバックループを追跡
|
|
@@ -837,6 +904,15 @@ musubi init
|
|
|
837
904
|
|
|
838
905
|
貢献を歓迎します!ガイドラインについては[CONTRIBUTING.md](CONTRIBUTING.md)を参照してください。
|
|
839
906
|
|
|
907
|
+
## ⭐ サポート
|
|
908
|
+
|
|
909
|
+
MUSUBIが役立つと感じたら、ぜひ:
|
|
910
|
+
|
|
911
|
+
- ⭐ **このリポジトリにスターを** - 他の人がMUSUBIを発見する助けになります
|
|
912
|
+
- 🐛 **問題を報告** - 改善にご協力ください
|
|
913
|
+
- 💡 **機能を提案** - あなたのアイデアを大切にします
|
|
914
|
+
- 📝 **体験を共有** - ブログでMUSUBIについて書いてください
|
|
915
|
+
|
|
840
916
|
## ライセンス
|
|
841
917
|
|
|
842
918
|
MITライセンス - 詳細は[LICENSE](LICENSE)を参照してください。
|
|
@@ -852,13 +928,22 @@ MUSUBIは以下のフレームワークから機能を統合しています。
|
|
|
852
928
|
- **cc-sdd** - Pラベル並列化、検証ゲート
|
|
853
929
|
- **spec-kit** - 憲法ガバナンス、テストファースト
|
|
854
930
|
|
|
855
|
-
## 詳細情報
|
|
931
|
+
## 📚 詳細情報
|
|
856
932
|
|
|
857
|
-
- [ドキュメント](
|
|
858
|
-
- [
|
|
859
|
-
- [プロジェクト計画](
|
|
860
|
-
- [
|
|
933
|
+
- [📖 ドキュメント](docs/)
|
|
934
|
+
- [📋 SRS v3.0.0](docs/requirements/srs/srs-musubi-v3.0.0.ja.md)
|
|
935
|
+
- [📅 プロジェクト計画 v3.0.0](docs/plans/project-plan-v3.0.0.ja.md)
|
|
936
|
+
- [🏗️ ブループリント](Ultimate-SDD-Tool-Blueprint-v3-25-Skills.md)
|
|
937
|
+
- [📊 プロジェクト計画](PROJECT-PLAN-MUSUBI.md)
|
|
861
938
|
|
|
862
939
|
---
|
|
863
940
|
|
|
864
|
-
|
|
941
|
+
<div align="center">
|
|
942
|
+
|
|
943
|
+
**🎋 MUSUBI** - むすび - 仕様、設計、コードを結びつける。
|
|
944
|
+
|
|
945
|
+
[](https://github.com/nahisaho/musubi)
|
|
946
|
+
|
|
947
|
+
Made with ❤️ for the AI Coding Community
|
|
948
|
+
|
|
949
|
+
</div>
|
package/README.md
CHANGED
|
@@ -1,14 +1,77 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# 🎋 MUSUBI
|
|
4
|
+
|
|
5
|
+
**Ultimate Specification Driven Development Tool**
|
|
2
6
|
|
|
3
7
|
[](https://github.com/nahisaho/musubi/actions/workflows/ci.yml)
|
|
4
8
|
[](https://www.npmjs.com/package/musubi-sdd)
|
|
9
|
+
[](https://www.npmjs.com/package/musubi-sdd)
|
|
5
10
|
[](https://opensource.org/licenses/MIT)
|
|
11
|
+
[](https://nodejs.org)
|
|
12
|
+
[](http://makeapullrequest.com)
|
|
13
|
+
|
|
14
|
+
[English](README.md) | [日本語](README.ja.md) | [Documentation](docs/) | [npm](https://www.npmjs.com/package/musubi-sdd)
|
|
15
|
+
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
> 🤖 **7 AI Coding Agents** × 📋 **25 Specialized Skills** × ⚖️ **Constitutional Governance**
|
|
21
|
+
|
|
22
|
+
MUSUBI (結び - "connection/binding") is a comprehensive **Specification Driven Development (SDD)** framework that synthesizes the best features from 6 leading frameworks into a production-ready tool for multiple AI coding agents.
|
|
23
|
+
|
|
24
|
+
<div align="center">
|
|
25
|
+
|
|
26
|
+

|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
## ✨ Why MUSUBI?
|
|
31
|
+
|
|
32
|
+
| Challenge | MUSUBI Solution |
|
|
33
|
+
|-----------|-----------------|
|
|
34
|
+
| 🔀 Fragmented AI tools | **7 agents, 1 unified workflow** |
|
|
35
|
+
| 📝 Ambiguous requirements | **EARS format with 5 patterns** |
|
|
36
|
+
| 🔍 Lost traceability | **100% Req→Design→Code→Test mapping** |
|
|
37
|
+
| ⚠️ Quality inconsistency | **9 Constitutional Articles + Phase -1 Gates** |
|
|
38
|
+
| 🔄 Brownfield challenges | **Delta specs + Change management** |
|
|
39
|
+
|
|
40
|
+
## 🚀 Quick Start
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Install and initialize in 30 seconds
|
|
44
|
+
npx musubi-sdd init
|
|
6
45
|
|
|
7
|
-
|
|
46
|
+
# For existing projects - auto-analyze and generate steering docs
|
|
47
|
+
npx musubi-sdd onboard
|
|
8
48
|
|
|
9
|
-
|
|
49
|
+
# That's it! Now use your AI agent with SDD commands:
|
|
50
|
+
# Claude Code: /sdd-requirements, /sdd-design, /sdd-implement
|
|
51
|
+
# GitHub Copilot: #sdd-requirements, #sdd-design, #sdd-implement
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
<details>
|
|
55
|
+
<summary>📦 More installation options</summary>
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# Global installation
|
|
59
|
+
npm install -g musubi-sdd
|
|
10
60
|
|
|
11
|
-
|
|
61
|
+
# Initialize for specific AI agent
|
|
62
|
+
musubi init --copilot # GitHub Copilot
|
|
63
|
+
musubi init --cursor # Cursor IDE
|
|
64
|
+
musubi init --gemini # Gemini CLI
|
|
65
|
+
musubi init --codex # Codex CLI
|
|
66
|
+
musubi init --qwen # Qwen Code
|
|
67
|
+
musubi init --windsurf # Windsurf IDE
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
</details>
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 📊 What's New in v2.1.0
|
|
12
75
|
|
|
13
76
|
- 🔄 **Workflow Engine** - New `musubi-workflow` CLI for stage management and metrics
|
|
14
77
|
- 📊 **Metrics Collection** - Track time per stage, iteration counts, feedback loops
|
|
@@ -1043,6 +1106,15 @@ musubi init
|
|
|
1043
1106
|
|
|
1044
1107
|
Contributions welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
1045
1108
|
|
|
1109
|
+
## ⭐ Support
|
|
1110
|
+
|
|
1111
|
+
If you find MUSUBI useful, please consider:
|
|
1112
|
+
|
|
1113
|
+
- ⭐ **Star this repository** - It helps others discover MUSUBI
|
|
1114
|
+
- 🐛 **Report issues** - Help us improve
|
|
1115
|
+
- 💡 **Suggest features** - We value your ideas
|
|
1116
|
+
- 📝 **Share your experience** - Write about MUSUBI on your blog
|
|
1117
|
+
|
|
1046
1118
|
## License
|
|
1047
1119
|
|
|
1048
1120
|
MIT License - see [LICENSE](LICENSE) for details.
|
|
@@ -1058,13 +1130,22 @@ MUSUBI synthesizes features from:
|
|
|
1058
1130
|
- **cc-sdd** - P-label parallelization, validation gates
|
|
1059
1131
|
- **spec-kit** - Constitutional governance, test-first
|
|
1060
1132
|
|
|
1061
|
-
## Learn More
|
|
1133
|
+
## 📚 Learn More
|
|
1062
1134
|
|
|
1063
|
-
- [Documentation](
|
|
1064
|
-
- [
|
|
1065
|
-
- [Project Plan](
|
|
1066
|
-
- [
|
|
1135
|
+
- [📖 Documentation](docs/)
|
|
1136
|
+
- [📋 SRS v3.0.0](docs/requirements/srs/srs-musubi-v3.0.0.md)
|
|
1137
|
+
- [📅 Project Plan v3.0.0](docs/plans/project-plan-v3.0.0.md)
|
|
1138
|
+
- [🏗️ Blueprint](Ultimate-SDD-Tool-Blueprint-v3-25-Skills.md)
|
|
1139
|
+
- [📊 Project Plan](PROJECT-PLAN-MUSUBI.md)
|
|
1067
1140
|
|
|
1068
1141
|
---
|
|
1069
1142
|
|
|
1070
|
-
|
|
1143
|
+
<div align="center">
|
|
1144
|
+
|
|
1145
|
+
**🎋 MUSUBI** - むすび - Bringing specifications, design, and code together.
|
|
1146
|
+
|
|
1147
|
+
[](https://github.com/nahisaho/musubi)
|
|
1148
|
+
|
|
1149
|
+
Made with ❤️ for the AI Coding Community
|
|
1150
|
+
|
|
1151
|
+
</div>
|
package/bin/musubi-analyze.js
CHANGED
|
@@ -60,10 +60,11 @@ program
|
|
|
60
60
|
.name('musubi-analyze')
|
|
61
61
|
.description('Analyze codebase for quality, complexity, and technical debt')
|
|
62
62
|
.version('0.5.0')
|
|
63
|
-
.option('-t, --type <type>', 'Analysis type: quality, dependencies, security, all', 'all')
|
|
63
|
+
.option('-t, --type <type>', 'Analysis type: quality, dependencies, security, stuck, all', 'all')
|
|
64
64
|
.option('-o, --output <file>', 'Output file for analysis report')
|
|
65
65
|
.option('--json', 'Output in JSON format')
|
|
66
66
|
.option('--threshold <level>', 'Quality threshold: low, medium, high', 'medium')
|
|
67
|
+
.option('--detect-stuck', 'Detect stuck agent patterns (repetitive errors, circular edits)')
|
|
67
68
|
.option('-v, --verbose', 'Verbose output')
|
|
68
69
|
.parse(process.argv);
|
|
69
70
|
|
|
@@ -405,6 +406,210 @@ async function generateReport(analysisData) {
|
|
|
405
406
|
log(`Report saved to: ${reportPath}`, 'success');
|
|
406
407
|
}
|
|
407
408
|
|
|
409
|
+
// ============================================================================
|
|
410
|
+
// Stuck Detection Analysis
|
|
411
|
+
// ============================================================================
|
|
412
|
+
|
|
413
|
+
async function analyzeStuckPatterns() {
|
|
414
|
+
log('Stuck Pattern Analysis', 'analyze');
|
|
415
|
+
console.log();
|
|
416
|
+
|
|
417
|
+
const stuckPatterns = {
|
|
418
|
+
isStuck: false,
|
|
419
|
+
confidence: 0,
|
|
420
|
+
patterns: [],
|
|
421
|
+
suggestions: []
|
|
422
|
+
};
|
|
423
|
+
|
|
424
|
+
try {
|
|
425
|
+
// Check git log for repetitive patterns
|
|
426
|
+
const { execSync } = require('child_process');
|
|
427
|
+
|
|
428
|
+
// Get recent commits
|
|
429
|
+
let commits = [];
|
|
430
|
+
try {
|
|
431
|
+
const gitLog = execSync(
|
|
432
|
+
'git log --oneline -20 --format="%h|%s" 2>/dev/null',
|
|
433
|
+
{ encoding: 'utf8' }
|
|
434
|
+
).trim();
|
|
435
|
+
commits = gitLog.split('\n').filter(Boolean).map(line => {
|
|
436
|
+
const [hash, ...msgParts] = line.split('|');
|
|
437
|
+
return { hash, message: msgParts.join('|') };
|
|
438
|
+
});
|
|
439
|
+
} catch {
|
|
440
|
+
// Not in git repo or no commits
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// Pattern 1: Repetitive revert/fix cycles
|
|
444
|
+
const revertPattern = commits.filter(c =>
|
|
445
|
+
c.message.toLowerCase().includes('revert') ||
|
|
446
|
+
c.message.toLowerCase().includes('undo')
|
|
447
|
+
);
|
|
448
|
+
if (revertPattern.length >= 3) {
|
|
449
|
+
stuckPatterns.patterns.push({
|
|
450
|
+
type: 'revert-cycle',
|
|
451
|
+
severity: 'high',
|
|
452
|
+
message: `${revertPattern.length} revert commits detected in recent history`,
|
|
453
|
+
commits: revertPattern.slice(0, 3).map(c => c.message)
|
|
454
|
+
});
|
|
455
|
+
stuckPatterns.confidence += 30;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// Pattern 2: Same file edited repeatedly
|
|
459
|
+
let recentChanges = [];
|
|
460
|
+
try {
|
|
461
|
+
const gitDiff = execSync(
|
|
462
|
+
'git diff --stat HEAD~5 HEAD 2>/dev/null',
|
|
463
|
+
{ encoding: 'utf8' }
|
|
464
|
+
).trim();
|
|
465
|
+
recentChanges = gitDiff.split('\n').filter(Boolean);
|
|
466
|
+
} catch {
|
|
467
|
+
// No recent changes or not enough history
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
const fileEditCounts = {};
|
|
471
|
+
for (let i = 0; i < Math.min(commits.length, 10); i++) {
|
|
472
|
+
try {
|
|
473
|
+
const files = execSync(
|
|
474
|
+
`git show --name-only --format= ${commits[i].hash} 2>/dev/null`,
|
|
475
|
+
{ encoding: 'utf8' }
|
|
476
|
+
).trim().split('\n').filter(Boolean);
|
|
477
|
+
files.forEach(f => {
|
|
478
|
+
fileEditCounts[f] = (fileEditCounts[f] || 0) + 1;
|
|
479
|
+
});
|
|
480
|
+
} catch {
|
|
481
|
+
// Skip this commit
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
const frequentlyEdited = Object.entries(fileEditCounts)
|
|
486
|
+
.filter(([, count]) => count >= 4)
|
|
487
|
+
.map(([file, count]) => ({ file, count }));
|
|
488
|
+
|
|
489
|
+
if (frequentlyEdited.length > 0) {
|
|
490
|
+
stuckPatterns.patterns.push({
|
|
491
|
+
type: 'circular-edit',
|
|
492
|
+
severity: 'medium',
|
|
493
|
+
message: 'Files being edited repeatedly without resolution',
|
|
494
|
+
files: frequentlyEdited
|
|
495
|
+
});
|
|
496
|
+
stuckPatterns.confidence += 25;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// Pattern 3: Test failures in recent runs
|
|
500
|
+
const testResultsPath = path.join(process.cwd(), 'coverage', 'test-results.json');
|
|
501
|
+
if (fs.existsSync(testResultsPath)) {
|
|
502
|
+
try {
|
|
503
|
+
const testResults = fs.readJsonSync(testResultsPath);
|
|
504
|
+
if (testResults.numFailedTests > 0) {
|
|
505
|
+
stuckPatterns.patterns.push({
|
|
506
|
+
type: 'test-failure',
|
|
507
|
+
severity: 'medium',
|
|
508
|
+
message: `${testResults.numFailedTests} tests failing`,
|
|
509
|
+
failedTests: testResults.testResults?.filter(t => t.status === 'failed').slice(0, 5)
|
|
510
|
+
});
|
|
511
|
+
stuckPatterns.confidence += 20;
|
|
512
|
+
}
|
|
513
|
+
} catch {
|
|
514
|
+
// Cannot read test results
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// Pattern 4: Error log patterns
|
|
519
|
+
const errorLogPath = path.join(process.cwd(), 'logs', 'error.log');
|
|
520
|
+
if (fs.existsSync(errorLogPath)) {
|
|
521
|
+
try {
|
|
522
|
+
const errorLog = fs.readFileSync(errorLogPath, 'utf8');
|
|
523
|
+
const recentErrors = errorLog.split('\n').slice(-50);
|
|
524
|
+
const errorCounts = {};
|
|
525
|
+
recentErrors.forEach(line => {
|
|
526
|
+
const match = line.match(/Error: (.+)/);
|
|
527
|
+
if (match) {
|
|
528
|
+
const key = match[1].slice(0, 50);
|
|
529
|
+
errorCounts[key] = (errorCounts[key] || 0) + 1;
|
|
530
|
+
}
|
|
531
|
+
});
|
|
532
|
+
|
|
533
|
+
const repetitiveErrors = Object.entries(errorCounts)
|
|
534
|
+
.filter(([, count]) => count >= 3)
|
|
535
|
+
.map(([error, count]) => ({ error, count }));
|
|
536
|
+
|
|
537
|
+
if (repetitiveErrors.length > 0) {
|
|
538
|
+
stuckPatterns.patterns.push({
|
|
539
|
+
type: 'repetitive-error',
|
|
540
|
+
severity: 'high',
|
|
541
|
+
message: 'Same errors occurring repeatedly',
|
|
542
|
+
errors: repetitiveErrors
|
|
543
|
+
});
|
|
544
|
+
stuckPatterns.confidence += 30;
|
|
545
|
+
}
|
|
546
|
+
} catch {
|
|
547
|
+
// Cannot read error log
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
// Determine if stuck
|
|
552
|
+
stuckPatterns.isStuck = stuckPatterns.confidence >= 50;
|
|
553
|
+
|
|
554
|
+
// Generate suggestions based on patterns
|
|
555
|
+
if (stuckPatterns.patterns.some(p => p.type === 'revert-cycle')) {
|
|
556
|
+
stuckPatterns.suggestions.push('Consider stepping back to review the overall approach');
|
|
557
|
+
stuckPatterns.suggestions.push('Break down the problem into smaller, testable pieces');
|
|
558
|
+
}
|
|
559
|
+
if (stuckPatterns.patterns.some(p => p.type === 'circular-edit')) {
|
|
560
|
+
stuckPatterns.suggestions.push('Focus on one file at a time and verify changes work');
|
|
561
|
+
stuckPatterns.suggestions.push('Run tests after each change to catch issues early');
|
|
562
|
+
}
|
|
563
|
+
if (stuckPatterns.patterns.some(p => p.type === 'test-failure')) {
|
|
564
|
+
stuckPatterns.suggestions.push('Fix failing tests before making new changes');
|
|
565
|
+
stuckPatterns.suggestions.push('Review test expectations vs implementation');
|
|
566
|
+
}
|
|
567
|
+
if (stuckPatterns.patterns.some(p => p.type === 'repetitive-error')) {
|
|
568
|
+
stuckPatterns.suggestions.push('Address root cause of repetitive errors');
|
|
569
|
+
stuckPatterns.suggestions.push('Consider using different approach if error persists');
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// Display results
|
|
573
|
+
if (stuckPatterns.isStuck) {
|
|
574
|
+
console.log(chalk.bold.red('🚨 Stuck Pattern Detected!\n'));
|
|
575
|
+
} else if (stuckPatterns.patterns.length > 0) {
|
|
576
|
+
console.log(chalk.bold.yellow('⚠️ Potential Issues Found\n'));
|
|
577
|
+
} else {
|
|
578
|
+
console.log(chalk.bold.green('✓ No stuck patterns detected\n'));
|
|
579
|
+
return stuckPatterns;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
console.log(chalk.dim(`Confidence: ${stuckPatterns.confidence}%\n`));
|
|
583
|
+
|
|
584
|
+
stuckPatterns.patterns.forEach(pattern => {
|
|
585
|
+
const severityColor = {
|
|
586
|
+
high: chalk.red,
|
|
587
|
+
medium: chalk.yellow,
|
|
588
|
+
low: chalk.blue
|
|
589
|
+
}[pattern.severity] || chalk.white;
|
|
590
|
+
|
|
591
|
+
console.log(severityColor(`[${pattern.severity.toUpperCase()}] ${pattern.type}`));
|
|
592
|
+
console.log(chalk.dim(` ${pattern.message}`));
|
|
593
|
+
console.log();
|
|
594
|
+
});
|
|
595
|
+
|
|
596
|
+
if (stuckPatterns.suggestions.length > 0) {
|
|
597
|
+
console.log(chalk.bold('Suggestions:'));
|
|
598
|
+
stuckPatterns.suggestions.forEach(s => {
|
|
599
|
+
console.log(chalk.cyan(` → ${s}`));
|
|
600
|
+
});
|
|
601
|
+
console.log();
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
return stuckPatterns;
|
|
605
|
+
} catch (error) {
|
|
606
|
+
if (options.verbose) {
|
|
607
|
+
log(`Stuck analysis error: ${error.message}`, 'error');
|
|
608
|
+
}
|
|
609
|
+
return stuckPatterns;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
|
|
408
613
|
// ============================================================================
|
|
409
614
|
// Main Function
|
|
410
615
|
// ============================================================================
|
|
@@ -415,6 +620,19 @@ async function main() {
|
|
|
415
620
|
const analysisData = {};
|
|
416
621
|
|
|
417
622
|
try {
|
|
623
|
+
// Handle --detect-stuck option
|
|
624
|
+
if (options.detectStuck || options.type === 'stuck') {
|
|
625
|
+
analysisData.stuck = await analyzeStuckPatterns();
|
|
626
|
+
|
|
627
|
+
if (options.json) {
|
|
628
|
+
console.log(JSON.stringify(analysisData.stuck, null, 2));
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
if (options.type === 'stuck') {
|
|
632
|
+
process.exit(analysisData.stuck?.isStuck ? 1 : 0);
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
|
|
418
636
|
if (options.type === 'quality' || options.type === 'all') {
|
|
419
637
|
analysisData.quality = await analyzeQuality();
|
|
420
638
|
}
|