musubi-sdd 5.1.0 → 5.6.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 (232) hide show
  1. package/README.ja.md +106 -48
  2. package/README.md +110 -32
  3. package/bin/musubi-analyze.js +74 -67
  4. package/bin/musubi-browser.js +27 -26
  5. package/bin/musubi-change.js +48 -47
  6. package/bin/musubi-checkpoint.js +10 -7
  7. package/bin/musubi-convert.js +25 -25
  8. package/bin/musubi-costs.js +27 -10
  9. package/bin/musubi-gui.js +52 -46
  10. package/bin/musubi-init.js +1952 -10
  11. package/bin/musubi-orchestrate.js +327 -239
  12. package/bin/musubi-remember.js +69 -56
  13. package/bin/musubi-resolve.js +53 -45
  14. package/bin/musubi-trace.js +51 -22
  15. package/bin/musubi-validate.js +39 -30
  16. package/bin/musubi-workflow.js +33 -34
  17. package/bin/musubi.js +39 -2
  18. package/package.json +1 -1
  19. package/src/agents/agent-loop.js +94 -95
  20. package/src/agents/agentic/code-generator.js +119 -109
  21. package/src/agents/agentic/code-reviewer.js +105 -108
  22. package/src/agents/agentic/index.js +4 -4
  23. package/src/agents/browser/action-executor.js +13 -13
  24. package/src/agents/browser/ai-comparator.js +11 -10
  25. package/src/agents/browser/context-manager.js +6 -6
  26. package/src/agents/browser/index.js +5 -5
  27. package/src/agents/browser/nl-parser.js +31 -46
  28. package/src/agents/browser/screenshot.js +2 -2
  29. package/src/agents/browser/test-generator.js +6 -4
  30. package/src/agents/function-tool.js +71 -65
  31. package/src/agents/index.js +7 -7
  32. package/src/agents/schema-generator.js +98 -94
  33. package/src/analyzers/ast-extractor.js +158 -146
  34. package/src/analyzers/codegraph-auto-update.js +858 -0
  35. package/src/analyzers/complexity-analyzer.js +536 -0
  36. package/src/analyzers/context-optimizer.js +241 -126
  37. package/src/analyzers/impact-analyzer.js +1 -1
  38. package/src/analyzers/large-project-analyzer.js +766 -0
  39. package/src/analyzers/repository-map.js +77 -81
  40. package/src/analyzers/security-analyzer.js +19 -11
  41. package/src/analyzers/stuck-detector.js +19 -17
  42. package/src/converters/index.js +78 -57
  43. package/src/converters/ir/types.js +12 -12
  44. package/src/converters/parsers/musubi-parser.js +134 -126
  45. package/src/converters/parsers/openapi-parser.js +70 -53
  46. package/src/converters/parsers/speckit-parser.js +239 -175
  47. package/src/converters/writers/musubi-writer.js +123 -118
  48. package/src/converters/writers/speckit-writer.js +124 -113
  49. package/src/generators/rust-migration-generator.js +512 -0
  50. package/src/gui/public/index.html +1365 -1211
  51. package/src/gui/server.js +41 -40
  52. package/src/gui/services/file-watcher.js +23 -8
  53. package/src/gui/services/project-scanner.js +26 -20
  54. package/src/gui/services/replanning-service.js +27 -23
  55. package/src/gui/services/traceability-service.js +8 -8
  56. package/src/gui/services/workflow-service.js +14 -7
  57. package/src/index.js +151 -0
  58. package/src/integrations/cicd.js +90 -104
  59. package/src/integrations/codegraph-mcp.js +643 -0
  60. package/src/integrations/documentation.js +142 -103
  61. package/src/integrations/examples.js +95 -80
  62. package/src/integrations/github-client.js +17 -17
  63. package/src/integrations/index.js +5 -5
  64. package/src/integrations/mcp/index.js +21 -21
  65. package/src/integrations/mcp/mcp-context-provider.js +76 -78
  66. package/src/integrations/mcp/mcp-discovery.js +74 -72
  67. package/src/integrations/mcp/mcp-tool-registry.js +99 -94
  68. package/src/integrations/mcp-connector.js +70 -66
  69. package/src/integrations/platforms.js +50 -49
  70. package/src/integrations/tool-discovery.js +37 -31
  71. package/src/llm-providers/anthropic-provider.js +11 -11
  72. package/src/llm-providers/base-provider.js +16 -18
  73. package/src/llm-providers/copilot-provider.js +22 -19
  74. package/src/llm-providers/index.js +26 -25
  75. package/src/llm-providers/ollama-provider.js +11 -11
  76. package/src/llm-providers/openai-provider.js +12 -12
  77. package/src/managers/agent-memory.js +36 -24
  78. package/src/managers/checkpoint-manager.js +4 -8
  79. package/src/managers/delta-spec.js +19 -19
  80. package/src/managers/index.js +13 -4
  81. package/src/managers/memory-condenser.js +35 -45
  82. package/src/managers/repo-skill-manager.js +57 -31
  83. package/src/managers/skill-loader.js +25 -22
  84. package/src/managers/skill-tools.js +36 -72
  85. package/src/managers/workflow.js +30 -22
  86. package/src/monitoring/cost-tracker.js +48 -46
  87. package/src/monitoring/incident-manager.js +116 -106
  88. package/src/monitoring/index.js +144 -134
  89. package/src/monitoring/observability.js +75 -62
  90. package/src/monitoring/quality-dashboard.js +45 -41
  91. package/src/monitoring/release-manager.js +63 -53
  92. package/src/orchestration/agent-skill-binding.js +39 -47
  93. package/src/orchestration/error-handler.js +65 -107
  94. package/src/orchestration/guardrails/base-guardrail.js +26 -24
  95. package/src/orchestration/guardrails/guardrail-rules.js +50 -64
  96. package/src/orchestration/guardrails/index.js +5 -5
  97. package/src/orchestration/guardrails/input-guardrail.js +58 -45
  98. package/src/orchestration/guardrails/output-guardrail.js +104 -81
  99. package/src/orchestration/guardrails/safety-check.js +79 -79
  100. package/src/orchestration/index.js +38 -55
  101. package/src/orchestration/mcp-tool-adapters.js +96 -99
  102. package/src/orchestration/orchestration-engine.js +21 -21
  103. package/src/orchestration/pattern-registry.js +60 -45
  104. package/src/orchestration/patterns/auto.js +34 -47
  105. package/src/orchestration/patterns/group-chat.js +59 -65
  106. package/src/orchestration/patterns/handoff.js +67 -65
  107. package/src/orchestration/patterns/human-in-loop.js +51 -72
  108. package/src/orchestration/patterns/nested.js +25 -40
  109. package/src/orchestration/patterns/sequential.js +35 -34
  110. package/src/orchestration/patterns/swarm.js +63 -56
  111. package/src/orchestration/patterns/triage.js +150 -109
  112. package/src/orchestration/reasoning/index.js +9 -9
  113. package/src/orchestration/reasoning/planning-engine.js +143 -140
  114. package/src/orchestration/reasoning/reasoning-engine.js +206 -144
  115. package/src/orchestration/reasoning/self-correction.js +121 -128
  116. package/src/orchestration/replanning/adaptive-goal-modifier.js +107 -112
  117. package/src/orchestration/replanning/alternative-generator.js +37 -42
  118. package/src/orchestration/replanning/config.js +63 -59
  119. package/src/orchestration/replanning/goal-progress-tracker.js +98 -100
  120. package/src/orchestration/replanning/index.js +24 -20
  121. package/src/orchestration/replanning/plan-evaluator.js +49 -50
  122. package/src/orchestration/replanning/plan-monitor.js +32 -28
  123. package/src/orchestration/replanning/proactive-path-optimizer.js +175 -178
  124. package/src/orchestration/replanning/replan-history.js +33 -26
  125. package/src/orchestration/replanning/replanning-engine.js +106 -108
  126. package/src/orchestration/skill-executor.js +107 -109
  127. package/src/orchestration/skill-registry.js +85 -89
  128. package/src/orchestration/workflow-examples.js +228 -231
  129. package/src/orchestration/workflow-executor.js +65 -68
  130. package/src/orchestration/workflow-orchestrator.js +72 -73
  131. package/src/phase4-integration.js +47 -40
  132. package/src/phase5-integration.js +89 -30
  133. package/src/reporters/coverage-report.js +82 -30
  134. package/src/reporters/hierarchical-reporter.js +498 -0
  135. package/src/reporters/traceability-matrix-report.js +29 -20
  136. package/src/resolvers/issue-resolver.js +43 -31
  137. package/src/steering/advanced-validation.js +133 -124
  138. package/src/steering/auto-updater.js +60 -73
  139. package/src/steering/index.js +6 -6
  140. package/src/steering/quality-metrics.js +41 -35
  141. package/src/steering/steering-auto-update.js +83 -86
  142. package/src/steering/steering-validator.js +98 -106
  143. package/src/steering/template-constraints.js +53 -54
  144. package/src/templates/agents/claude-code/CLAUDE.md +32 -32
  145. package/src/templates/agents/claude-code/skills/agent-assistant/SKILL.md +13 -5
  146. package/src/templates/agents/claude-code/skills/ai-ml-engineer/mlops-guide.md +23 -23
  147. package/src/templates/agents/claude-code/skills/ai-ml-engineer/model-card-template.md +60 -41
  148. package/src/templates/agents/claude-code/skills/api-designer/api-patterns.md +27 -19
  149. package/src/templates/agents/claude-code/skills/api-designer/openapi-template.md +11 -7
  150. package/src/templates/agents/claude-code/skills/bug-hunter/SKILL.md +4 -3
  151. package/src/templates/agents/claude-code/skills/bug-hunter/root-cause-analysis.md +37 -15
  152. package/src/templates/agents/claude-code/skills/change-impact-analyzer/dependency-graph-patterns.md +36 -42
  153. package/src/templates/agents/claude-code/skills/change-impact-analyzer/impact-analysis-template.md +69 -60
  154. package/src/templates/agents/claude-code/skills/cloud-architect/aws-patterns.md +31 -38
  155. package/src/templates/agents/claude-code/skills/cloud-architect/azure-patterns.md +28 -23
  156. package/src/templates/agents/claude-code/skills/code-reviewer/SKILL.md +61 -0
  157. package/src/templates/agents/claude-code/skills/code-reviewer/best-practices.md +27 -0
  158. package/src/templates/agents/claude-code/skills/code-reviewer/review-checklist.md +29 -10
  159. package/src/templates/agents/claude-code/skills/code-reviewer/review-standards.md +29 -24
  160. package/src/templates/agents/claude-code/skills/constitution-enforcer/SKILL.md +8 -6
  161. package/src/templates/agents/claude-code/skills/constitution-enforcer/constitutional-articles.md +62 -26
  162. package/src/templates/agents/claude-code/skills/constitution-enforcer/phase-minus-one-gates.md +35 -16
  163. package/src/templates/agents/claude-code/skills/database-administrator/backup-recovery.md +27 -17
  164. package/src/templates/agents/claude-code/skills/database-administrator/tuning-guide.md +25 -20
  165. package/src/templates/agents/claude-code/skills/database-schema-designer/schema-patterns.md +39 -22
  166. package/src/templates/agents/claude-code/skills/devops-engineer/ci-cd-templates.md +25 -22
  167. package/src/templates/agents/claude-code/skills/issue-resolver/SKILL.md +24 -21
  168. package/src/templates/agents/claude-code/skills/orchestrator/SKILL.md +148 -63
  169. package/src/templates/agents/claude-code/skills/orchestrator/patterns.md +35 -16
  170. package/src/templates/agents/claude-code/skills/orchestrator/selection-matrix.md +69 -64
  171. package/src/templates/agents/claude-code/skills/performance-engineer/optimization-playbook.md +47 -47
  172. package/src/templates/agents/claude-code/skills/performance-optimizer/SKILL.md +69 -0
  173. package/src/templates/agents/claude-code/skills/performance-optimizer/benchmark-template.md +63 -45
  174. package/src/templates/agents/claude-code/skills/performance-optimizer/optimization-patterns.md +33 -35
  175. package/src/templates/agents/claude-code/skills/project-manager/SKILL.md +7 -6
  176. package/src/templates/agents/claude-code/skills/project-manager/agile-ceremonies.md +47 -28
  177. package/src/templates/agents/claude-code/skills/project-manager/project-templates.md +94 -78
  178. package/src/templates/agents/claude-code/skills/quality-assurance/SKILL.md +20 -17
  179. package/src/templates/agents/claude-code/skills/quality-assurance/qa-plan-template.md +63 -49
  180. package/src/templates/agents/claude-code/skills/release-coordinator/SKILL.md +5 -5
  181. package/src/templates/agents/claude-code/skills/release-coordinator/feature-flag-guide.md +30 -26
  182. package/src/templates/agents/claude-code/skills/release-coordinator/release-plan-template.md +67 -35
  183. package/src/templates/agents/claude-code/skills/requirements-analyst/ears-format.md +54 -42
  184. package/src/templates/agents/claude-code/skills/requirements-analyst/validation-rules.md +36 -33
  185. package/src/templates/agents/claude-code/skills/security-auditor/SKILL.md +77 -19
  186. package/src/templates/agents/claude-code/skills/security-auditor/audit-checklists.md +24 -24
  187. package/src/templates/agents/claude-code/skills/security-auditor/owasp-top-10.md +61 -20
  188. package/src/templates/agents/claude-code/skills/security-auditor/vulnerability-patterns.md +43 -11
  189. package/src/templates/agents/claude-code/skills/site-reliability-engineer/SKILL.md +1 -0
  190. package/src/templates/agents/claude-code/skills/site-reliability-engineer/incident-response-template.md +55 -25
  191. package/src/templates/agents/claude-code/skills/site-reliability-engineer/observability-patterns.md +78 -68
  192. package/src/templates/agents/claude-code/skills/site-reliability-engineer/slo-sli-guide.md +73 -53
  193. package/src/templates/agents/claude-code/skills/software-developer/solid-principles.md +83 -37
  194. package/src/templates/agents/claude-code/skills/software-developer/test-first-workflow.md +38 -31
  195. package/src/templates/agents/claude-code/skills/steering/SKILL.md +1 -0
  196. package/src/templates/agents/claude-code/skills/steering/auto-update-rules.md +31 -0
  197. package/src/templates/agents/claude-code/skills/system-architect/adr-template.md +25 -7
  198. package/src/templates/agents/claude-code/skills/system-architect/c4-model-guide.md +74 -61
  199. package/src/templates/agents/claude-code/skills/technical-writer/doc-templates/documentation-templates.md +70 -52
  200. package/src/templates/agents/claude-code/skills/test-engineer/SKILL.md +2 -0
  201. package/src/templates/agents/claude-code/skills/test-engineer/ears-test-mapping.md +75 -71
  202. package/src/templates/agents/claude-code/skills/test-engineer/test-types.md +85 -63
  203. package/src/templates/agents/claude-code/skills/traceability-auditor/coverage-matrix-template.md +39 -36
  204. package/src/templates/agents/claude-code/skills/traceability-auditor/gap-detection-rules.md +22 -17
  205. package/src/templates/agents/claude-code/skills/ui-ux-designer/SKILL.md +1 -0
  206. package/src/templates/agents/claude-code/skills/ui-ux-designer/accessibility-guidelines.md +49 -75
  207. package/src/templates/agents/claude-code/skills/ui-ux-designer/design-system-components.md +71 -59
  208. package/src/templates/agents/codex/AGENTS.md +74 -42
  209. package/src/templates/agents/cursor/AGENTS.md +74 -42
  210. package/src/templates/agents/gemini-cli/GEMINI.md +74 -42
  211. package/src/templates/agents/github-copilot/AGENTS.md +83 -51
  212. package/src/templates/agents/qwen-code/QWEN.md +74 -42
  213. package/src/templates/agents/windsurf/AGENTS.md +74 -42
  214. package/src/templates/architectures/README.md +41 -0
  215. package/src/templates/architectures/clean-architecture/README.md +113 -0
  216. package/src/templates/architectures/event-driven/README.md +162 -0
  217. package/src/templates/architectures/hexagonal/README.md +130 -0
  218. package/src/templates/index.js +6 -1
  219. package/src/templates/locale-manager.js +16 -16
  220. package/src/templates/shared/delta-spec-template.md +20 -13
  221. package/src/templates/shared/github-actions/musubi-issue-resolver.yml +5 -5
  222. package/src/templates/shared/github-actions/musubi-security-check.yml +3 -3
  223. package/src/templates/shared/github-actions/musubi-validate.yml +4 -4
  224. package/src/templates/shared/steering/structure.md +95 -0
  225. package/src/templates/skills/browser-agent.md +21 -16
  226. package/src/templates/skills/web-gui.md +8 -0
  227. package/src/templates/template-constraints.js +50 -53
  228. package/src/validators/advanced-validation.js +30 -36
  229. package/src/validators/constitutional-validator.js +77 -73
  230. package/src/validators/critic-system.js +49 -59
  231. package/src/validators/delta-format.js +59 -55
  232. package/src/validators/traceability-validator.js +7 -11
@@ -0,0 +1,498 @@
1
+ /**
2
+ * MUSUBI Hierarchical Reporter
3
+ *
4
+ * Generates hierarchical, drilldown-capable reports for large projects:
5
+ * - Module/directory-based grouping
6
+ * - Hotspot identification
7
+ * - Interactive drill-down support
8
+ * - Multiple output formats
9
+ *
10
+ * Designed for projects with 10,000+ files (like GCC with 109,073 files)
11
+ *
12
+ * @version 5.5.0
13
+ */
14
+
15
+ const fs = require('fs-extra');
16
+ // const path = require('path');
17
+
18
+ // ============================================================================
19
+ // Hierarchical Reporter
20
+ // ============================================================================
21
+
22
+ class HierarchicalReporter {
23
+ constructor(options = {}) {
24
+ this.options = {
25
+ maxDepth: 4,
26
+ hotspotThreshold: 25,
27
+ groupingDepth: 3,
28
+ outputFormat: 'markdown',
29
+ ...options,
30
+ };
31
+ }
32
+
33
+ /**
34
+ * Generate hierarchical report from analysis results
35
+ */
36
+ generateReport(analysis, options = {}) {
37
+ const mergedOptions = { ...this.options, ...options };
38
+
39
+ const report = {
40
+ generatedAt: new Date().toISOString(),
41
+ projectPath: analysis.projectPath || process.cwd(),
42
+ summary: this.generateSummary(analysis),
43
+ hierarchy: this.buildHierarchy(
44
+ analysis.files || analysis.results?.files || [],
45
+ mergedOptions.groupingDepth
46
+ ),
47
+ hotspots: this.identifyHotspots(analysis, mergedOptions.hotspotThreshold),
48
+ trends: this.analyzeTrends(analysis),
49
+ recommendations: this.generateRecommendations(analysis),
50
+ };
51
+
52
+ return report;
53
+ }
54
+
55
+ /**
56
+ * Generate executive summary
57
+ */
58
+ generateSummary(analysis) {
59
+ const files = analysis.files || analysis.results?.files || [];
60
+ const summary = analysis.summary || analysis.results?.summary || {};
61
+
62
+ return {
63
+ totalFiles: files.length,
64
+ totalLines: summary.totalLines || files.reduce((sum, f) => sum + (f.lines || 0), 0),
65
+ averageComplexity: summary.averageComplexity || this.calculateAverage(files, 'complexity'),
66
+ averageMaintainability:
67
+ summary.averageMaintainability || this.calculateAverage(files, 'maintainability'),
68
+ languageDistribution:
69
+ summary.languageDistribution || this.calculateLanguageDistribution(files),
70
+ issueCount: this.countIssues(files),
71
+ healthScore: this.calculateHealthScore(files),
72
+ };
73
+ }
74
+
75
+ /**
76
+ * Build hierarchical tree from file list
77
+ */
78
+ buildHierarchy(files, depth = 3) {
79
+ const tree = {
80
+ name: 'root',
81
+ path: '',
82
+ stats: {
83
+ files: 0,
84
+ lines: 0,
85
+ complexity: 0,
86
+ issues: 0,
87
+ },
88
+ children: {},
89
+ };
90
+
91
+ for (const file of files) {
92
+ const filePath = file.path || file.absolutePath || '';
93
+ const parts = filePath.split('/').filter(p => p);
94
+ const relevantParts = parts.slice(0, depth);
95
+
96
+ let current = tree;
97
+ let currentPath = '';
98
+
99
+ for (let i = 0; i < relevantParts.length; i++) {
100
+ const part = relevantParts[i];
101
+ currentPath = currentPath ? `${currentPath}/${part}` : part;
102
+
103
+ if (!current.children[part]) {
104
+ current.children[part] = {
105
+ name: part,
106
+ path: currentPath,
107
+ stats: {
108
+ files: 0,
109
+ lines: 0,
110
+ complexity: 0,
111
+ issues: 0,
112
+ },
113
+ children: {},
114
+ };
115
+ }
116
+
117
+ current = current.children[part];
118
+
119
+ // Add stats to each level
120
+ current.stats.files++;
121
+ current.stats.lines += file.lines || 0;
122
+ current.stats.complexity += file.complexity || 0;
123
+ current.stats.issues += file.issueCount || file.issues?.length || 0;
124
+ }
125
+
126
+ // Add to root
127
+ tree.stats.files++;
128
+ tree.stats.lines += file.lines || 0;
129
+ tree.stats.complexity += file.complexity || 0;
130
+ tree.stats.issues += file.issueCount || file.issues?.length || 0;
131
+ }
132
+
133
+ // Calculate averages for each node
134
+ this.calculateNodeAverages(tree);
135
+
136
+ return tree;
137
+ }
138
+
139
+ /**
140
+ * Calculate averages for a node and its children recursively
141
+ */
142
+ calculateNodeAverages(node) {
143
+ if (node.stats.files > 0) {
144
+ node.stats.averageComplexity = Math.round(node.stats.complexity / node.stats.files);
145
+ node.stats.issuesPerFile = Math.round((node.stats.issues / node.stats.files) * 100) / 100;
146
+ }
147
+
148
+ for (const child of Object.values(node.children)) {
149
+ this.calculateNodeAverages(child);
150
+ }
151
+ }
152
+
153
+ /**
154
+ * Identify hotspots (high-complexity, high-issue areas)
155
+ */
156
+ identifyHotspots(analysis, threshold = 25) {
157
+ const files = analysis.files || analysis.results?.files || [];
158
+ const hotspots = [];
159
+
160
+ // File-level hotspots
161
+ for (const file of files) {
162
+ const complexity = file.complexity || 0;
163
+ const issues = file.issueCount || file.issues?.length || 0;
164
+
165
+ if (complexity >= threshold || issues >= 3) {
166
+ hotspots.push({
167
+ type: 'file',
168
+ path: file.path,
169
+ complexity,
170
+ issues,
171
+ reason: complexity >= threshold ? 'high-complexity' : 'many-issues',
172
+ severity: complexity >= 50 || issues >= 5 ? 'critical' : 'warning',
173
+ });
174
+ }
175
+ }
176
+
177
+ // Function-level hotspots (from giant functions)
178
+ const giantFunctions = analysis.results?.giantFunctions || [];
179
+ for (const func of giantFunctions) {
180
+ hotspots.push({
181
+ type: 'function',
182
+ path: `${func.file}:${func.name}`,
183
+ lines: func.lines,
184
+ reason: 'giant-function',
185
+ severity: func.lines >= 1000 ? 'critical' : 'warning',
186
+ });
187
+ }
188
+
189
+ // Directory-level hotspots
190
+ const hierarchy = this.buildHierarchy(files, 2);
191
+ for (const [name, node] of Object.entries(hierarchy.children)) {
192
+ if (node.stats.averageComplexity >= threshold || node.stats.issuesPerFile >= 2) {
193
+ hotspots.push({
194
+ type: 'directory',
195
+ path: name,
196
+ files: node.stats.files,
197
+ averageComplexity: node.stats.averageComplexity,
198
+ issuesPerFile: node.stats.issuesPerFile,
199
+ reason: 'concentrated-issues',
200
+ severity: node.stats.averageComplexity >= 50 ? 'critical' : 'warning',
201
+ });
202
+ }
203
+ }
204
+
205
+ // Sort by severity and complexity
206
+ return hotspots.sort((a, b) => {
207
+ if (a.severity === 'critical' && b.severity !== 'critical') return -1;
208
+ if (a.severity !== 'critical' && b.severity === 'critical') return 1;
209
+ return (b.complexity || b.lines || 0) - (a.complexity || a.lines || 0);
210
+ });
211
+ }
212
+
213
+ /**
214
+ * Analyze trends (for comparison with previous analyses)
215
+ */
216
+ analyzeTrends(analysis) {
217
+ // This would compare with historical data if available
218
+ const files = analysis.files || analysis.results?.files || [];
219
+
220
+ const complexityDistribution = {
221
+ low: 0,
222
+ medium: 0,
223
+ high: 0,
224
+ extreme: 0,
225
+ };
226
+
227
+ for (const file of files) {
228
+ const c = file.complexity || 0;
229
+ if (c < 10) complexityDistribution.low++;
230
+ else if (c < 25) complexityDistribution.medium++;
231
+ else if (c < 50) complexityDistribution.high++;
232
+ else complexityDistribution.extreme++;
233
+ }
234
+
235
+ return {
236
+ complexityDistribution,
237
+ timestamp: new Date().toISOString(),
238
+ // Future: compare with previous analysis
239
+ };
240
+ }
241
+
242
+ /**
243
+ * Generate recommendations based on analysis
244
+ */
245
+ generateRecommendations(analysis) {
246
+ const recommendations = [];
247
+ const files = analysis.files || analysis.results?.files || [];
248
+ const summary = analysis.summary || analysis.results?.summary || {};
249
+ const hotspots = this.identifyHotspots(analysis);
250
+
251
+ // Giant functions
252
+ const giantFunctions = analysis.results?.giantFunctions || [];
253
+ if (giantFunctions.length > 0) {
254
+ recommendations.push({
255
+ priority: 'P0',
256
+ category: 'refactoring',
257
+ title: 'Refactor Giant Functions',
258
+ description: `${giantFunctions.length} functions exceed 1000 lines`,
259
+ impact: 'Significantly improves maintainability and testability',
260
+ effort: 'High',
261
+ items: giantFunctions.slice(0, 5).map(f => `${f.file}:${f.name} (${f.lines} lines)`),
262
+ });
263
+ }
264
+
265
+ // Critical hotspots
266
+ const criticalHotspots = hotspots.filter(h => h.severity === 'critical');
267
+ if (criticalHotspots.length > 0) {
268
+ recommendations.push({
269
+ priority: 'P1',
270
+ category: 'quality',
271
+ title: 'Address Critical Hotspots',
272
+ description: `${criticalHotspots.length} critical areas need attention`,
273
+ impact: 'Reduces bug risk and improves code health',
274
+ effort: 'Medium',
275
+ items: criticalHotspots.slice(0, 5).map(h => `${h.path} (${h.reason})`),
276
+ });
277
+ }
278
+
279
+ // Low maintainability
280
+ const avgMaintainability =
281
+ summary.averageMaintainability || this.calculateAverage(files, 'maintainability');
282
+ if (avgMaintainability < 40) {
283
+ recommendations.push({
284
+ priority: 'P2',
285
+ category: 'documentation',
286
+ title: 'Improve Code Documentation',
287
+ description: `Average maintainability index is ${avgMaintainability} (target: >60)`,
288
+ impact: 'Easier onboarding and reduced knowledge silos',
289
+ effort: 'Low',
290
+ items: [
291
+ 'Add JSDoc/docstring comments to public functions',
292
+ 'Document complex algorithms inline',
293
+ 'Create architecture documentation',
294
+ ],
295
+ });
296
+ }
297
+
298
+ // Language diversity
299
+ const languages = Object.keys(
300
+ summary.languageDistribution || this.calculateLanguageDistribution(files)
301
+ );
302
+ if (languages.length > 5) {
303
+ recommendations.push({
304
+ priority: 'P3',
305
+ category: 'architecture',
306
+ title: 'Consider Language Consolidation',
307
+ description: `${languages.length} different languages detected`,
308
+ impact: 'Simplified tooling and reduced context switching',
309
+ effort: 'High',
310
+ items: languages,
311
+ });
312
+ }
313
+
314
+ return recommendations;
315
+ }
316
+
317
+ /**
318
+ * Calculate average of a property across files
319
+ */
320
+ calculateAverage(files, property) {
321
+ if (files.length === 0) return 0;
322
+ const sum = files.reduce((acc, f) => acc + (f[property] || 0), 0);
323
+ return Math.round(sum / files.length);
324
+ }
325
+
326
+ /**
327
+ * Calculate language distribution
328
+ */
329
+ calculateLanguageDistribution(files) {
330
+ const distribution = {};
331
+ for (const file of files) {
332
+ const lang = file.language || 'unknown';
333
+ distribution[lang] = (distribution[lang] || 0) + 1;
334
+ }
335
+ return distribution;
336
+ }
337
+
338
+ /**
339
+ * Count total issues across files
340
+ */
341
+ countIssues(files) {
342
+ return files.reduce((sum, f) => sum + (f.issueCount || f.issues?.length || 0), 0);
343
+ }
344
+
345
+ /**
346
+ * Calculate overall health score (0-100)
347
+ */
348
+ calculateHealthScore(files) {
349
+ if (files.length === 0) return 100;
350
+
351
+ const avgComplexity = this.calculateAverage(files, 'complexity');
352
+ const avgMaintainability = this.calculateAverage(files, 'maintainability');
353
+ const issueRatio = this.countIssues(files) / files.length;
354
+
355
+ // Weighted score
356
+ const complexityScore = Math.max(0, 100 - avgComplexity * 2);
357
+ const maintainabilityScore = avgMaintainability;
358
+ const issueScore = Math.max(0, 100 - issueRatio * 20);
359
+
360
+ return Math.round(complexityScore * 0.3 + maintainabilityScore * 0.4 + issueScore * 0.3);
361
+ }
362
+
363
+ /**
364
+ * Get drill-down data for a specific path
365
+ */
366
+ drillDown(report, targetPath) {
367
+ const pathParts = targetPath.split('/').filter(p => p);
368
+ let current = report.hierarchy;
369
+
370
+ for (const part of pathParts) {
371
+ if (current.children && current.children[part]) {
372
+ current = current.children[part];
373
+ } else {
374
+ return null;
375
+ }
376
+ }
377
+
378
+ return {
379
+ path: targetPath,
380
+ stats: current.stats,
381
+ children: Object.entries(current.children).map(([name, node]) => ({
382
+ name,
383
+ path: node.path,
384
+ stats: node.stats,
385
+ hasChildren: Object.keys(node.children).length > 0,
386
+ })),
387
+ };
388
+ }
389
+
390
+ /**
391
+ * Format report as Markdown
392
+ */
393
+ formatAsMarkdown(report) {
394
+ let md = '# Hierarchical Code Analysis Report\n\n';
395
+ md += `**Generated**: ${report.generatedAt}\n`;
396
+ md += `**Project**: ${report.projectPath}\n\n`;
397
+
398
+ // Summary
399
+ md += '## Executive Summary\n\n';
400
+ md += `| Metric | Value |\n|--------|-------|\n`;
401
+ md += `| Total Files | ${report.summary.totalFiles.toLocaleString()} |\n`;
402
+ md += `| Total Lines | ${report.summary.totalLines.toLocaleString()} |\n`;
403
+ md += `| Average Complexity | ${report.summary.averageComplexity} |\n`;
404
+ md += `| Average Maintainability | ${report.summary.averageMaintainability} |\n`;
405
+ md += `| Total Issues | ${report.summary.issueCount} |\n`;
406
+ md += `| Health Score | ${report.summary.healthScore}/100 |\n\n`;
407
+
408
+ // Language distribution
409
+ md += '### Language Distribution\n\n';
410
+ md += '| Language | Files |\n|----------|-------|\n';
411
+ for (const [lang, count] of Object.entries(report.summary.languageDistribution)) {
412
+ md += `| ${lang} | ${count} |\n`;
413
+ }
414
+ md += '\n';
415
+
416
+ // Hierarchy (top level)
417
+ md += '## Project Structure\n\n';
418
+ md += '| Directory | Files | Lines | Avg Complexity | Issues |\n';
419
+ md += '|-----------|-------|-------|----------------|--------|\n';
420
+ for (const [name, node] of Object.entries(report.hierarchy.children)) {
421
+ md += `| ${name}/ | ${node.stats.files} | ${node.stats.lines.toLocaleString()} | ${node.stats.averageComplexity} | ${node.stats.issues} |\n`;
422
+ }
423
+ md += '\n';
424
+
425
+ // Hotspots
426
+ if (report.hotspots.length > 0) {
427
+ md += '## Hotspots\n\n';
428
+ md += '| Type | Path | Severity | Reason |\n';
429
+ md += '|------|------|----------|--------|\n';
430
+ for (const hotspot of report.hotspots.slice(0, 20)) {
431
+ md += `| ${hotspot.type} | ${hotspot.path} | ${hotspot.severity} | ${hotspot.reason} |\n`;
432
+ }
433
+ md += '\n';
434
+ }
435
+
436
+ // Recommendations
437
+ if (report.recommendations.length > 0) {
438
+ md += '## Recommendations\n\n';
439
+ for (const rec of report.recommendations) {
440
+ md += `### ${rec.priority}: ${rec.title}\n\n`;
441
+ md += `**Category**: ${rec.category}\n`;
442
+ md += `**Impact**: ${rec.impact}\n`;
443
+ md += `**Effort**: ${rec.effort}\n\n`;
444
+ md += `${rec.description}\n\n`;
445
+ if (rec.items && rec.items.length > 0) {
446
+ md += 'Items:\n';
447
+ for (const item of rec.items) {
448
+ md += `- ${item}\n`;
449
+ }
450
+ md += '\n';
451
+ }
452
+ }
453
+ }
454
+
455
+ // Complexity distribution
456
+ md += '## Complexity Distribution\n\n';
457
+ md += '| Level | File Count |\n|-------|------------|\n';
458
+ for (const [level, count] of Object.entries(report.trends.complexityDistribution)) {
459
+ md += `| ${level} | ${count} |\n`;
460
+ }
461
+
462
+ return md;
463
+ }
464
+
465
+ /**
466
+ * Format report as JSON
467
+ */
468
+ formatAsJson(report) {
469
+ return JSON.stringify(report, null, 2);
470
+ }
471
+
472
+ /**
473
+ * Save report to file
474
+ */
475
+ async saveReport(report, outputPath, format = 'markdown') {
476
+ let content;
477
+ let extension;
478
+
479
+ switch (format) {
480
+ case 'json':
481
+ content = this.formatAsJson(report);
482
+ extension = '.json';
483
+ break;
484
+ case 'markdown':
485
+ default:
486
+ content = this.formatAsMarkdown(report);
487
+ extension = '.md';
488
+ break;
489
+ }
490
+
491
+ const finalPath = outputPath.endsWith(extension) ? outputPath : outputPath + extension;
492
+ await fs.writeFile(finalPath, content, 'utf8');
493
+
494
+ return finalPath;
495
+ }
496
+ }
497
+
498
+ module.exports = { HierarchicalReporter };
@@ -415,11 +415,12 @@ class TraceabilityMatrixReport {
415
415
  return '<tr><td colspan="6" style="text-align: center;">No requirements found</td></tr>';
416
416
  }
417
417
 
418
- return forward.map(item => {
419
- const req = item.requirement;
420
- const reqId = req?.id || req?.file || 'Unknown';
418
+ return forward
419
+ .map(item => {
420
+ const req = item.requirement;
421
+ const reqId = req?.id || req?.file || 'Unknown';
421
422
 
422
- return `
423
+ return `
423
424
  <tr data-complete="${item.complete}">
424
425
  <td><code>${this.escapeHtml(reqId)}</code></td>
425
426
  <td>${this.formatLinks(item.design, 'design')}</td>
@@ -433,7 +434,8 @@ class TraceabilityMatrixReport {
433
434
  </td>
434
435
  </tr>
435
436
  `;
436
- }).join('');
437
+ })
438
+ .join('');
437
439
  }
438
440
 
439
441
  /**
@@ -444,11 +446,12 @@ class TraceabilityMatrixReport {
444
446
  return '<tr><td colspan="6" style="text-align: center;">No tests found</td></tr>';
445
447
  }
446
448
 
447
- return backward.map(item => {
448
- const test = item.test;
449
- const testId = test?.file || test?.id || 'Unknown';
449
+ return backward
450
+ .map(item => {
451
+ const test = item.test;
452
+ const testId = test?.file || test?.id || 'Unknown';
450
453
 
451
- return `
454
+ return `
452
455
  <tr data-complete="${item.complete}">
453
456
  <td><code>${this.escapeHtml(path.basename(testId))}</code></td>
454
457
  <td>${this.formatLinks(item.code, 'code')}</td>
@@ -462,7 +465,8 @@ class TraceabilityMatrixReport {
462
465
  </td>
463
466
  </tr>
464
467
  `;
465
- }).join('');
468
+ })
469
+ .join('');
466
470
  }
467
471
 
468
472
  /**
@@ -473,11 +477,13 @@ class TraceabilityMatrixReport {
473
477
  return `<span class="badge missing">None</span>`;
474
478
  }
475
479
 
476
- return items.map(item => {
477
- const id = item?.id || item?.file || 'Unknown';
478
- const displayId = path.basename(id);
479
- return `<span class="badge link chain-node ${type}">${this.escapeHtml(displayId)}</span>`;
480
- }).join(' ');
480
+ return items
481
+ .map(item => {
482
+ const id = item?.id || item?.file || 'Unknown';
483
+ const displayId = path.basename(id);
484
+ return `<span class="badge link chain-node ${type}">${this.escapeHtml(displayId)}</span>`;
485
+ })
486
+ .join(' ');
481
487
  }
482
488
 
483
489
  /**
@@ -518,10 +524,12 @@ class TraceabilityMatrixReport {
518
524
  <h3 class="collapsible" onclick="toggleCollapsible(this)">${category} (${items.length})</h3>
519
525
  <div class="collapsible-content">
520
526
  <ul>
521
- ${items.map(item => {
522
- const id = item?.id || item?.file || 'Unknown';
523
- return `<li><code>${this.escapeHtml(id)}</code></li>`;
524
- }).join('')}
527
+ ${items
528
+ .map(item => {
529
+ const id = item?.id || item?.file || 'Unknown';
530
+ return `<li><code>${this.escapeHtml(id)}</code></li>`;
531
+ })
532
+ .join('')}
525
533
  </ul>
526
534
  </div>
527
535
  </div>
@@ -669,7 +677,8 @@ Generated: ${data.timestamp}
669
677
  const outputDir = path.join(this.workspaceRoot, this.options.outputDir);
670
678
  await fs.ensureDir(outputDir);
671
679
 
672
- const extension = format === ReportFormat.HTML ? '.html' : format === ReportFormat.MARKDOWN ? '.md' : '.json';
680
+ const extension =
681
+ format === ReportFormat.HTML ? '.html' : format === ReportFormat.MARKDOWN ? '.md' : '.json';
673
682
  const fullPath = path.join(outputDir, filename + extension);
674
683
 
675
684
  await fs.writeFile(fullPath, report, 'utf8');