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,643 @@
1
+ /**
2
+ * MUSUBI CodeGraph MCP Integration
3
+ *
4
+ * Deep integration with CodeGraph MCP for:
5
+ * - Function call graph analysis
6
+ * - Impact analysis for changes
7
+ * - Dependency chain tracking
8
+ * - Community detection
9
+ *
10
+ * Based on analysis of GCC codebase with 1,436,920 relations
11
+ *
12
+ * @version 5.5.0
13
+ */
14
+
15
+ const fs = require('fs-extra');
16
+ const path = require('path');
17
+ const { spawn, execSync } = require('child_process');
18
+ const Database = require('better-sqlite3');
19
+
20
+ // ============================================================================
21
+ // CodeGraph Integration
22
+ // ============================================================================
23
+
24
+ class CodeGraphIntegration {
25
+ constructor(repoPath, options = {}) {
26
+ this.repoPath = repoPath;
27
+ this.dbPath = path.join(repoPath, '.codegraph', 'graph.db');
28
+ this.options = {
29
+ fullIndex: false,
30
+ noCommunity: false,
31
+ ...options,
32
+ };
33
+ this.db = null;
34
+ }
35
+
36
+ /**
37
+ * Check if CodeGraph MCP is installed
38
+ */
39
+ static isInstalled() {
40
+ try {
41
+ execSync('which codegraph-mcp', { encoding: 'utf8', stdio: 'pipe' });
42
+ return true;
43
+ } catch {
44
+ return false;
45
+ }
46
+ }
47
+
48
+ /**
49
+ * Check if index exists
50
+ */
51
+ hasIndex() {
52
+ return fs.existsSync(this.dbPath);
53
+ }
54
+
55
+ /**
56
+ * Initialize or update CodeGraph index
57
+ */
58
+ async indexRepository(options = {}) {
59
+ const args = ['index', this.repoPath];
60
+
61
+ if (options.full || this.options.fullIndex) {
62
+ args.push('--full');
63
+ }
64
+
65
+ if (options.noCommunity || this.options.noCommunity) {
66
+ args.push('--no-community');
67
+ }
68
+
69
+ return new Promise((resolve, reject) => {
70
+ console.log(`📊 Indexing repository: ${this.repoPath}`);
71
+ const proc = spawn('codegraph-mcp', args, {
72
+ stdio: ['pipe', 'pipe', 'pipe'],
73
+ });
74
+
75
+ let stdout = '';
76
+ let stderr = '';
77
+
78
+ proc.stdout.on('data', data => {
79
+ stdout += data.toString();
80
+ });
81
+
82
+ proc.stderr.on('data', data => {
83
+ stderr += data.toString();
84
+ });
85
+
86
+ proc.on('close', code => {
87
+ if (code === 0) {
88
+ resolve({ success: true, output: stdout });
89
+ } else {
90
+ reject(new Error(`CodeGraph indexing failed: ${stderr}`));
91
+ }
92
+ });
93
+
94
+ proc.on('error', error => {
95
+ reject(error);
96
+ });
97
+ });
98
+ }
99
+
100
+ /**
101
+ * Open database connection
102
+ */
103
+ open() {
104
+ if (!this.hasIndex()) {
105
+ throw new Error(`CodeGraph index not found at ${this.dbPath}. Run indexRepository() first.`);
106
+ }
107
+ this.db = new Database(this.dbPath, { readonly: true });
108
+ return this;
109
+ }
110
+
111
+ /**
112
+ * Close database connection
113
+ */
114
+ close() {
115
+ if (this.db) {
116
+ this.db.close();
117
+ this.db = null;
118
+ }
119
+ }
120
+
121
+ /**
122
+ * Get repository statistics
123
+ */
124
+ getStats() {
125
+ this.ensureOpen();
126
+
127
+ const entityCount = this.db.prepare('SELECT COUNT(*) as count FROM entities').get().count;
128
+ const fileCount = this.db
129
+ .prepare("SELECT COUNT(*) as count FROM entities WHERE type = 'module'")
130
+ .get().count;
131
+ const relationCount = this.db.prepare('SELECT COUNT(*) as count FROM relations').get().count;
132
+
133
+ const entityTypes = this.db
134
+ .prepare(
135
+ `
136
+ SELECT type, COUNT(*) as count
137
+ FROM entities
138
+ GROUP BY type
139
+ ORDER BY count DESC
140
+ `
141
+ )
142
+ .all();
143
+
144
+ const relationTypes = this.db
145
+ .prepare(
146
+ `
147
+ SELECT type, COUNT(*) as count
148
+ FROM relations
149
+ GROUP BY type
150
+ ORDER BY count DESC
151
+ `
152
+ )
153
+ .all();
154
+
155
+ return {
156
+ entities: entityCount,
157
+ files: fileCount,
158
+ relations: relationCount,
159
+ entityTypes,
160
+ relationTypes,
161
+ };
162
+ }
163
+
164
+ /**
165
+ * Get call graph for a function
166
+ */
167
+ getCallGraph(functionName, options = {}) {
168
+ this.ensureOpen();
169
+
170
+ const depth = options.depth || 3;
171
+ const direction = options.direction || 'both'; // 'callers', 'callees', 'both'
172
+
173
+ const result = {
174
+ function: functionName,
175
+ callers: [],
176
+ callees: [],
177
+ };
178
+
179
+ // Get function entity
180
+ const entity = this.db
181
+ .prepare(
182
+ `
183
+ SELECT id, name, file, start_line, end_line
184
+ FROM entities
185
+ WHERE name = ? AND type = 'function'
186
+ LIMIT 1
187
+ `
188
+ )
189
+ .get(functionName);
190
+
191
+ if (!entity) {
192
+ return { error: `Function "${functionName}" not found` };
193
+ }
194
+
195
+ result.entity = entity;
196
+
197
+ // Get callees (functions this function calls)
198
+ if (direction === 'callees' || direction === 'both') {
199
+ result.callees = this.getCallees(entity.id, depth);
200
+ }
201
+
202
+ // Get callers (functions that call this function)
203
+ if (direction === 'callers' || direction === 'both') {
204
+ result.callers = this.getCallers(entity.id, depth);
205
+ }
206
+
207
+ return result;
208
+ }
209
+
210
+ /**
211
+ * Get functions called by given function (recursive)
212
+ */
213
+ getCallees(entityId, depth, visited = new Set()) {
214
+ if (depth <= 0 || visited.has(entityId)) return [];
215
+ visited.add(entityId);
216
+
217
+ const callees = this.db
218
+ .prepare(
219
+ `
220
+ SELECT e.id, e.name, e.file, e.start_line, r.type as relation_type
221
+ FROM relations r
222
+ JOIN entities e ON r.target_id = e.id
223
+ WHERE r.source_id = ?
224
+ AND r.type IN ('calls', 'invokes', 'references')
225
+ AND e.type = 'function'
226
+ `
227
+ )
228
+ .all(entityId);
229
+
230
+ return callees.map(callee => ({
231
+ ...callee,
232
+ callees: depth > 1 ? this.getCallees(callee.id, depth - 1, visited) : [],
233
+ }));
234
+ }
235
+
236
+ /**
237
+ * Get functions that call given function (recursive)
238
+ */
239
+ getCallers(entityId, depth, visited = new Set()) {
240
+ if (depth <= 0 || visited.has(entityId)) return [];
241
+ visited.add(entityId);
242
+
243
+ const callers = this.db
244
+ .prepare(
245
+ `
246
+ SELECT e.id, e.name, e.file, e.start_line, r.type as relation_type
247
+ FROM relations r
248
+ JOIN entities e ON r.source_id = e.id
249
+ WHERE r.target_id = ?
250
+ AND r.type IN ('calls', 'invokes', 'references')
251
+ AND e.type = 'function'
252
+ `
253
+ )
254
+ .all(entityId);
255
+
256
+ return callers.map(caller => ({
257
+ ...caller,
258
+ callers: depth > 1 ? this.getCallers(caller.id, depth - 1, visited) : [],
259
+ }));
260
+ }
261
+
262
+ /**
263
+ * Analyze impact of changes to specified files
264
+ */
265
+ async analyzeImpact(changedFiles) {
266
+ this.ensureOpen();
267
+
268
+ const impact = {
269
+ changedFiles,
270
+ directlyAffected: new Set(),
271
+ transitivelyAffected: new Set(),
272
+ affectedTests: [],
273
+ affectedDocs: [],
274
+ riskLevel: 'low',
275
+ summary: {},
276
+ };
277
+
278
+ for (const file of changedFiles) {
279
+ // Get all entities in changed file
280
+ const entities = this.db
281
+ .prepare(
282
+ `
283
+ SELECT id, name, type
284
+ FROM entities
285
+ WHERE file LIKE ?
286
+ `
287
+ )
288
+ .all(`%${file}%`);
289
+
290
+ for (const entity of entities) {
291
+ // Find all entities that depend on changed entities
292
+ const dependents = this.db
293
+ .prepare(
294
+ `
295
+ SELECT DISTINCT e.file, e.name, e.type
296
+ FROM relations r
297
+ JOIN entities e ON r.source_id = e.id
298
+ WHERE r.target_id = ?
299
+ `
300
+ )
301
+ .all(entity.id);
302
+
303
+ for (const dep of dependents) {
304
+ if (!changedFiles.includes(dep.file)) {
305
+ impact.directlyAffected.add(dep.file);
306
+ }
307
+ }
308
+ }
309
+ }
310
+
311
+ // Convert Sets to arrays
312
+ impact.directlyAffected = [...impact.directlyAffected];
313
+
314
+ // Find transitive dependencies
315
+ const toCheck = [...impact.directlyAffected];
316
+ const checked = new Set(changedFiles);
317
+
318
+ while (toCheck.length > 0) {
319
+ const file = toCheck.pop();
320
+ if (checked.has(file)) continue;
321
+ checked.add(file);
322
+
323
+ const entities = this.db
324
+ .prepare(
325
+ `
326
+ SELECT id FROM entities WHERE file LIKE ?
327
+ `
328
+ )
329
+ .all(`%${file}%`);
330
+
331
+ for (const entity of entities) {
332
+ const dependents = this.db
333
+ .prepare(
334
+ `
335
+ SELECT DISTINCT e.file
336
+ FROM relations r
337
+ JOIN entities e ON r.source_id = e.id
338
+ WHERE r.target_id = ?
339
+ `
340
+ )
341
+ .all(entity.id);
342
+
343
+ for (const dep of dependents) {
344
+ if (!checked.has(dep.file) && !changedFiles.includes(dep.file)) {
345
+ impact.transitivelyAffected.add(dep.file);
346
+ toCheck.push(dep.file);
347
+ }
348
+ }
349
+ }
350
+ }
351
+
352
+ impact.transitivelyAffected = [...impact.transitivelyAffected];
353
+
354
+ // Find affected tests
355
+ const allAffected = [...impact.directlyAffected, ...impact.transitivelyAffected];
356
+ impact.affectedTests = allAffected.filter(
357
+ f => f.includes('test') || f.includes('spec') || f.includes('__tests__')
358
+ );
359
+
360
+ // Calculate risk level
361
+ const totalAffected = allAffected.length;
362
+ if (totalAffected > 100) {
363
+ impact.riskLevel = 'critical';
364
+ } else if (totalAffected > 50) {
365
+ impact.riskLevel = 'high';
366
+ } else if (totalAffected > 20) {
367
+ impact.riskLevel = 'medium';
368
+ } else {
369
+ impact.riskLevel = 'low';
370
+ }
371
+
372
+ // Summary
373
+ impact.summary = {
374
+ changedFiles: changedFiles.length,
375
+ directlyAffected: impact.directlyAffected.length,
376
+ transitivelyAffected: impact.transitivelyAffected.length,
377
+ affectedTests: impact.affectedTests.length,
378
+ totalImpact: totalAffected,
379
+ riskLevel: impact.riskLevel,
380
+ };
381
+
382
+ return impact;
383
+ }
384
+
385
+ /**
386
+ * Get largest functions in the codebase
387
+ */
388
+ getLargestFunctions(limit = 50) {
389
+ this.ensureOpen();
390
+
391
+ return this.db
392
+ .prepare(
393
+ `
394
+ SELECT
395
+ name,
396
+ file,
397
+ start_line,
398
+ end_line,
399
+ (end_line - start_line) as lines
400
+ FROM entities
401
+ WHERE type = 'function'
402
+ AND end_line > start_line
403
+ ORDER BY (end_line - start_line) DESC
404
+ LIMIT ?
405
+ `
406
+ )
407
+ .all(limit);
408
+ }
409
+
410
+ /**
411
+ * Get most connected entities (potential refactoring candidates)
412
+ */
413
+ getMostConnected(limit = 50) {
414
+ this.ensureOpen();
415
+
416
+ return this.db
417
+ .prepare(
418
+ `
419
+ SELECT
420
+ e.name,
421
+ e.file,
422
+ e.type,
423
+ COUNT(DISTINCT r1.source_id) as incoming,
424
+ COUNT(DISTINCT r2.target_id) as outgoing,
425
+ COUNT(DISTINCT r1.source_id) + COUNT(DISTINCT r2.target_id) as total_connections
426
+ FROM entities e
427
+ LEFT JOIN relations r1 ON e.id = r1.target_id
428
+ LEFT JOIN relations r2 ON e.id = r2.source_id
429
+ GROUP BY e.id
430
+ ORDER BY total_connections DESC
431
+ LIMIT ?
432
+ `
433
+ )
434
+ .all(limit);
435
+ }
436
+
437
+ /**
438
+ * Find circular dependencies
439
+ */
440
+ findCircularDependencies(maxDepth = 5) {
441
+ this.ensureOpen();
442
+
443
+ const cycles = [];
444
+ const visited = new Set();
445
+
446
+ // Get all modules
447
+ const modules = this.db
448
+ .prepare(
449
+ `
450
+ SELECT id, name, file FROM entities WHERE type = 'module' LIMIT 1000
451
+ `
452
+ )
453
+ .all();
454
+
455
+ for (const module of modules) {
456
+ const path = [module.file];
457
+ this.findCycles(module.id, path, visited, cycles, maxDepth);
458
+ }
459
+
460
+ return cycles;
461
+ }
462
+
463
+ /**
464
+ * Helper to find cycles (DFS)
465
+ */
466
+ findCycles(entityId, path, visited, cycles, depth) {
467
+ if (depth <= 0) return;
468
+ if (visited.has(entityId)) return;
469
+
470
+ const deps = this.db
471
+ .prepare(
472
+ `
473
+ SELECT DISTINCT e.id, e.file
474
+ FROM relations r
475
+ JOIN entities e ON r.target_id = e.id
476
+ WHERE r.source_id = ?
477
+ AND e.type = 'module'
478
+ AND r.type IN ('imports', 'includes', 'requires')
479
+ `
480
+ )
481
+ .all(entityId);
482
+
483
+ for (const dep of deps) {
484
+ if (path.includes(dep.file)) {
485
+ const cycleStart = path.indexOf(dep.file);
486
+ cycles.push([...path.slice(cycleStart), dep.file]);
487
+ } else {
488
+ this.findCycles(dep.id, [...path, dep.file], visited, cycles, depth - 1);
489
+ }
490
+ }
491
+
492
+ visited.add(entityId);
493
+ }
494
+
495
+ /**
496
+ * Get file dependencies
497
+ */
498
+ getFileDependencies(filePath) {
499
+ this.ensureOpen();
500
+
501
+ const imports = this.db
502
+ .prepare(
503
+ `
504
+ SELECT DISTINCT
505
+ target.file as imported_file,
506
+ target.name as imported_name,
507
+ r.type as relation_type
508
+ FROM entities source
509
+ JOIN relations r ON source.id = r.source_id
510
+ JOIN entities target ON r.target_id = target.id
511
+ WHERE source.file LIKE ?
512
+ AND r.type IN ('imports', 'includes', 'requires', 'references')
513
+ AND target.type = 'module'
514
+ `
515
+ )
516
+ .all(`%${filePath}%`);
517
+
518
+ const exports = this.db
519
+ .prepare(
520
+ `
521
+ SELECT DISTINCT
522
+ source.file as importing_file,
523
+ source.name as importing_name,
524
+ r.type as relation_type
525
+ FROM entities target
526
+ JOIN relations r ON target.id = r.target_id
527
+ JOIN entities source ON r.source_id = source.id
528
+ WHERE target.file LIKE ?
529
+ AND r.type IN ('imports', 'includes', 'requires', 'references')
530
+ AND source.type = 'module'
531
+ `
532
+ )
533
+ .all(`%${filePath}%`);
534
+
535
+ return { imports, exports };
536
+ }
537
+
538
+ /**
539
+ * Search entities by pattern
540
+ */
541
+ searchEntities(pattern, options = {}) {
542
+ this.ensureOpen();
543
+
544
+ const type = options.type || null;
545
+ const limit = options.limit || 100;
546
+
547
+ let query = `
548
+ SELECT id, name, type, file, start_line, end_line
549
+ FROM entities
550
+ WHERE name LIKE ?
551
+ `;
552
+
553
+ const params = [`%${pattern}%`];
554
+
555
+ if (type) {
556
+ query += ' AND type = ?';
557
+ params.push(type);
558
+ }
559
+
560
+ query += ' ORDER BY name LIMIT ?';
561
+ params.push(limit);
562
+
563
+ return this.db.prepare(query).all(...params);
564
+ }
565
+
566
+ /**
567
+ * Get community information (if available)
568
+ */
569
+ getCommunities() {
570
+ this.ensureOpen();
571
+
572
+ try {
573
+ return this.db
574
+ .prepare(
575
+ `
576
+ SELECT
577
+ community_id,
578
+ COUNT(*) as member_count,
579
+ GROUP_CONCAT(name, ', ') as members
580
+ FROM entities
581
+ WHERE community_id IS NOT NULL
582
+ GROUP BY community_id
583
+ ORDER BY member_count DESC
584
+ LIMIT 50
585
+ `
586
+ )
587
+ .all();
588
+ } catch (error) {
589
+ return { error: 'Community data not available. Re-index without --no-community flag.' };
590
+ }
591
+ }
592
+
593
+ /**
594
+ * Ensure database is open
595
+ */
596
+ ensureOpen() {
597
+ if (!this.db) {
598
+ this.open();
599
+ }
600
+ }
601
+
602
+ /**
603
+ * Generate markdown report
604
+ */
605
+ generateReport() {
606
+ const stats = this.getStats();
607
+ const largestFunctions = this.getLargestFunctions(20);
608
+ const mostConnected = this.getMostConnected(20);
609
+
610
+ let report = '# CodeGraph Analysis Report\n\n';
611
+ report += `**Generated**: ${new Date().toISOString()}\n`;
612
+ report += `**Repository**: ${this.repoPath}\n\n`;
613
+
614
+ report += '## Statistics\n\n';
615
+ report += `- Total Entities: ${stats.entities.toLocaleString()}\n`;
616
+ report += `- Total Files: ${stats.files.toLocaleString()}\n`;
617
+ report += `- Total Relations: ${stats.relations.toLocaleString()}\n\n`;
618
+
619
+ report += '### Entity Types\n\n';
620
+ report += '| Type | Count |\n|------|-------|\n';
621
+ for (const { type, count } of stats.entityTypes) {
622
+ report += `| ${type} | ${count.toLocaleString()} |\n`;
623
+ }
624
+ report += '\n';
625
+
626
+ report += '## Largest Functions (Refactoring Candidates)\n\n';
627
+ report += '| Function | File | Lines |\n|----------|------|-------|\n';
628
+ for (const func of largestFunctions) {
629
+ report += `| ${func.name} | ${func.file} | ${func.lines} |\n`;
630
+ }
631
+ report += '\n';
632
+
633
+ report += '## Most Connected Entities (High Coupling)\n\n';
634
+ report += '| Entity | Type | Connections |\n|--------|------|-------------|\n';
635
+ for (const entity of mostConnected) {
636
+ report += `| ${entity.name} | ${entity.type} | ${entity.total_connections} |\n`;
637
+ }
638
+
639
+ return report;
640
+ }
641
+ }
642
+
643
+ module.exports = { CodeGraphIntegration };