openlore 2.0.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.
Files changed (634) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +268 -0
  3. package/dist/api/analyze.d.ts +17 -0
  4. package/dist/api/analyze.d.ts.map +1 -0
  5. package/dist/api/analyze.js +143 -0
  6. package/dist/api/analyze.js.map +1 -0
  7. package/dist/api/audit.d.ts +10 -0
  8. package/dist/api/audit.d.ts.map +1 -0
  9. package/dist/api/audit.js +117 -0
  10. package/dist/api/audit.js.map +1 -0
  11. package/dist/api/decisions.d.ts +55 -0
  12. package/dist/api/decisions.d.ts.map +1 -0
  13. package/dist/api/decisions.js +157 -0
  14. package/dist/api/decisions.js.map +1 -0
  15. package/dist/api/drift.d.ts +21 -0
  16. package/dist/api/drift.d.ts.map +1 -0
  17. package/dist/api/drift.js +152 -0
  18. package/dist/api/drift.js.map +1 -0
  19. package/dist/api/generate.d.ts +18 -0
  20. package/dist/api/generate.d.ts.map +1 -0
  21. package/dist/api/generate.js +259 -0
  22. package/dist/api/generate.js.map +1 -0
  23. package/dist/api/index.d.ts +41 -0
  24. package/dist/api/index.d.ts.map +1 -0
  25. package/dist/api/index.js +34 -0
  26. package/dist/api/index.js.map +1 -0
  27. package/dist/api/init.d.ts +18 -0
  28. package/dist/api/init.d.ts.map +1 -0
  29. package/dist/api/init.js +83 -0
  30. package/dist/api/init.js.map +1 -0
  31. package/dist/api/run.d.ts +19 -0
  32. package/dist/api/run.d.ts.map +1 -0
  33. package/dist/api/run.js +312 -0
  34. package/dist/api/run.js.map +1 -0
  35. package/dist/api/specs.d.ts +49 -0
  36. package/dist/api/specs.d.ts.map +1 -0
  37. package/dist/api/specs.js +137 -0
  38. package/dist/api/specs.js.map +1 -0
  39. package/dist/api/types.d.ts +201 -0
  40. package/dist/api/types.d.ts.map +1 -0
  41. package/dist/api/types.js +9 -0
  42. package/dist/api/types.js.map +1 -0
  43. package/dist/api/verify.d.ts +20 -0
  44. package/dist/api/verify.d.ts.map +1 -0
  45. package/dist/api/verify.js +117 -0
  46. package/dist/api/verify.js.map +1 -0
  47. package/dist/cli/commands/analyze.d.ts +30 -0
  48. package/dist/cli/commands/analyze.d.ts.map +1 -0
  49. package/dist/cli/commands/analyze.js +683 -0
  50. package/dist/cli/commands/analyze.js.map +1 -0
  51. package/dist/cli/commands/audit.d.ts +9 -0
  52. package/dist/cli/commands/audit.d.ts.map +1 -0
  53. package/dist/cli/commands/audit.js +98 -0
  54. package/dist/cli/commands/audit.js.map +1 -0
  55. package/dist/cli/commands/decisions.d.ts +16 -0
  56. package/dist/cli/commands/decisions.d.ts.map +1 -0
  57. package/dist/cli/commands/decisions.js +864 -0
  58. package/dist/cli/commands/decisions.js.map +1 -0
  59. package/dist/cli/commands/digest.d.ts +9 -0
  60. package/dist/cli/commands/digest.d.ts.map +1 -0
  61. package/dist/cli/commands/digest.js +61 -0
  62. package/dist/cli/commands/digest.js.map +1 -0
  63. package/dist/cli/commands/doctor.d.ts +9 -0
  64. package/dist/cli/commands/doctor.d.ts.map +1 -0
  65. package/dist/cli/commands/doctor.js +398 -0
  66. package/dist/cli/commands/doctor.js.map +1 -0
  67. package/dist/cli/commands/drift.d.ts +9 -0
  68. package/dist/cli/commands/drift.d.ts.map +1 -0
  69. package/dist/cli/commands/drift.js +550 -0
  70. package/dist/cli/commands/drift.js.map +1 -0
  71. package/dist/cli/commands/generate.d.ts +9 -0
  72. package/dist/cli/commands/generate.d.ts.map +1 -0
  73. package/dist/cli/commands/generate.js +565 -0
  74. package/dist/cli/commands/generate.js.map +1 -0
  75. package/dist/cli/commands/init.d.ts +9 -0
  76. package/dist/cli/commands/init.d.ts.map +1 -0
  77. package/dist/cli/commands/init.js +173 -0
  78. package/dist/cli/commands/init.js.map +1 -0
  79. package/dist/cli/commands/mcp.d.ts +2235 -0
  80. package/dist/cli/commands/mcp.d.ts.map +1 -0
  81. package/dist/cli/commands/mcp.js +1384 -0
  82. package/dist/cli/commands/mcp.js.map +1 -0
  83. package/dist/cli/commands/refresh-stories.d.ts +10 -0
  84. package/dist/cli/commands/refresh-stories.d.ts.map +1 -0
  85. package/dist/cli/commands/refresh-stories.js +314 -0
  86. package/dist/cli/commands/refresh-stories.js.map +1 -0
  87. package/dist/cli/commands/run.d.ts +9 -0
  88. package/dist/cli/commands/run.d.ts.map +1 -0
  89. package/dist/cli/commands/run.js +459 -0
  90. package/dist/cli/commands/run.js.map +1 -0
  91. package/dist/cli/commands/setup.d.ts +19 -0
  92. package/dist/cli/commands/setup.d.ts.map +1 -0
  93. package/dist/cli/commands/setup.js +355 -0
  94. package/dist/cli/commands/setup.js.map +1 -0
  95. package/dist/cli/commands/test.d.ts +22 -0
  96. package/dist/cli/commands/test.d.ts.map +1 -0
  97. package/dist/cli/commands/test.js +180 -0
  98. package/dist/cli/commands/test.js.map +1 -0
  99. package/dist/cli/commands/verify.d.ts +9 -0
  100. package/dist/cli/commands/verify.d.ts.map +1 -0
  101. package/dist/cli/commands/verify.js +383 -0
  102. package/dist/cli/commands/verify.js.map +1 -0
  103. package/dist/cli/commands/view.d.ts +13 -0
  104. package/dist/cli/commands/view.d.ts.map +1 -0
  105. package/dist/cli/commands/view.js +547 -0
  106. package/dist/cli/commands/view.js.map +1 -0
  107. package/dist/cli/index.d.ts +9 -0
  108. package/dist/cli/index.d.ts.map +1 -0
  109. package/dist/cli/index.js +118 -0
  110. package/dist/cli/index.js.map +1 -0
  111. package/dist/cli/tui-approval.d.ts +11 -0
  112. package/dist/cli/tui-approval.d.ts.map +1 -0
  113. package/dist/cli/tui-approval.js +129 -0
  114. package/dist/cli/tui-approval.js.map +1 -0
  115. package/dist/constants.d.ts +314 -0
  116. package/dist/constants.d.ts.map +1 -0
  117. package/dist/constants.js +382 -0
  118. package/dist/constants.js.map +1 -0
  119. package/dist/core/analyzer/ai-config-generator.d.ts +54 -0
  120. package/dist/core/analyzer/ai-config-generator.d.ts.map +1 -0
  121. package/dist/core/analyzer/ai-config-generator.js +98 -0
  122. package/dist/core/analyzer/ai-config-generator.js.map +1 -0
  123. package/dist/core/analyzer/architecture-writer.d.ts +67 -0
  124. package/dist/core/analyzer/architecture-writer.d.ts.map +1 -0
  125. package/dist/core/analyzer/architecture-writer.js +209 -0
  126. package/dist/core/analyzer/architecture-writer.js.map +1 -0
  127. package/dist/core/analyzer/artifact-generator.d.ts +261 -0
  128. package/dist/core/analyzer/artifact-generator.d.ts.map +1 -0
  129. package/dist/core/analyzer/artifact-generator.js +909 -0
  130. package/dist/core/analyzer/artifact-generator.js.map +1 -0
  131. package/dist/core/analyzer/ast-chunker.d.ts +24 -0
  132. package/dist/core/analyzer/ast-chunker.d.ts.map +1 -0
  133. package/dist/core/analyzer/ast-chunker.js +198 -0
  134. package/dist/core/analyzer/ast-chunker.js.map +1 -0
  135. package/dist/core/analyzer/call-graph.d.ts +162 -0
  136. package/dist/core/analyzer/call-graph.d.ts.map +1 -0
  137. package/dist/core/analyzer/call-graph.js +2040 -0
  138. package/dist/core/analyzer/call-graph.js.map +1 -0
  139. package/dist/core/analyzer/code-shaper.d.ts +33 -0
  140. package/dist/core/analyzer/code-shaper.d.ts.map +1 -0
  141. package/dist/core/analyzer/code-shaper.js +154 -0
  142. package/dist/core/analyzer/code-shaper.js.map +1 -0
  143. package/dist/core/analyzer/codebase-digest.d.ts +40 -0
  144. package/dist/core/analyzer/codebase-digest.d.ts.map +1 -0
  145. package/dist/core/analyzer/codebase-digest.js +195 -0
  146. package/dist/core/analyzer/codebase-digest.js.map +1 -0
  147. package/dist/core/analyzer/cpp-header-resolver.d.ts +30 -0
  148. package/dist/core/analyzer/cpp-header-resolver.d.ts.map +1 -0
  149. package/dist/core/analyzer/cpp-header-resolver.js +71 -0
  150. package/dist/core/analyzer/cpp-header-resolver.js.map +1 -0
  151. package/dist/core/analyzer/dependency-graph.d.ts +230 -0
  152. package/dist/core/analyzer/dependency-graph.d.ts.map +1 -0
  153. package/dist/core/analyzer/dependency-graph.js +752 -0
  154. package/dist/core/analyzer/dependency-graph.js.map +1 -0
  155. package/dist/core/analyzer/duplicate-detector.d.ts +52 -0
  156. package/dist/core/analyzer/duplicate-detector.d.ts.map +1 -0
  157. package/dist/core/analyzer/duplicate-detector.js +289 -0
  158. package/dist/core/analyzer/duplicate-detector.js.map +1 -0
  159. package/dist/core/analyzer/embedding-service.d.ts +56 -0
  160. package/dist/core/analyzer/embedding-service.d.ts.map +1 -0
  161. package/dist/core/analyzer/embedding-service.js +118 -0
  162. package/dist/core/analyzer/embedding-service.js.map +1 -0
  163. package/dist/core/analyzer/env-extractor.d.ts +33 -0
  164. package/dist/core/analyzer/env-extractor.d.ts.map +1 -0
  165. package/dist/core/analyzer/env-extractor.js +196 -0
  166. package/dist/core/analyzer/env-extractor.js.map +1 -0
  167. package/dist/core/analyzer/external-packages.d.ts +20 -0
  168. package/dist/core/analyzer/external-packages.d.ts.map +1 -0
  169. package/dist/core/analyzer/external-packages.js +175 -0
  170. package/dist/core/analyzer/external-packages.js.map +1 -0
  171. package/dist/core/analyzer/file-walker.d.ts +78 -0
  172. package/dist/core/analyzer/file-walker.d.ts.map +1 -0
  173. package/dist/core/analyzer/file-walker.js +532 -0
  174. package/dist/core/analyzer/file-walker.js.map +1 -0
  175. package/dist/core/analyzer/function-registry-trie.d.ts +21 -0
  176. package/dist/core/analyzer/function-registry-trie.d.ts.map +1 -0
  177. package/dist/core/analyzer/function-registry-trie.js +39 -0
  178. package/dist/core/analyzer/function-registry-trie.js.map +1 -0
  179. package/dist/core/analyzer/http-route-parser.d.ts +152 -0
  180. package/dist/core/analyzer/http-route-parser.d.ts.map +1 -0
  181. package/dist/core/analyzer/http-route-parser.js +971 -0
  182. package/dist/core/analyzer/http-route-parser.js.map +1 -0
  183. package/dist/core/analyzer/import-parser.d.ts +100 -0
  184. package/dist/core/analyzer/import-parser.d.ts.map +1 -0
  185. package/dist/core/analyzer/import-parser.js +952 -0
  186. package/dist/core/analyzer/import-parser.js.map +1 -0
  187. package/dist/core/analyzer/import-resolver-bridge.d.ts +25 -0
  188. package/dist/core/analyzer/import-resolver-bridge.d.ts.map +1 -0
  189. package/dist/core/analyzer/import-resolver-bridge.js +99 -0
  190. package/dist/core/analyzer/import-resolver-bridge.js.map +1 -0
  191. package/dist/core/analyzer/index.d.ts +10 -0
  192. package/dist/core/analyzer/index.d.ts.map +1 -0
  193. package/dist/core/analyzer/index.js +10 -0
  194. package/dist/core/analyzer/index.js.map +1 -0
  195. package/dist/core/analyzer/middleware-extractor.d.ts +29 -0
  196. package/dist/core/analyzer/middleware-extractor.d.ts.map +1 -0
  197. package/dist/core/analyzer/middleware-extractor.js +195 -0
  198. package/dist/core/analyzer/middleware-extractor.js.map +1 -0
  199. package/dist/core/analyzer/refactor-analyzer.d.ts +83 -0
  200. package/dist/core/analyzer/refactor-analyzer.d.ts.map +1 -0
  201. package/dist/core/analyzer/refactor-analyzer.js +351 -0
  202. package/dist/core/analyzer/refactor-analyzer.js.map +1 -0
  203. package/dist/core/analyzer/repository-mapper.d.ts +150 -0
  204. package/dist/core/analyzer/repository-mapper.d.ts.map +1 -0
  205. package/dist/core/analyzer/repository-mapper.js +740 -0
  206. package/dist/core/analyzer/repository-mapper.js.map +1 -0
  207. package/dist/core/analyzer/schema-extractor.d.ts +41 -0
  208. package/dist/core/analyzer/schema-extractor.d.ts.map +1 -0
  209. package/dist/core/analyzer/schema-extractor.js +229 -0
  210. package/dist/core/analyzer/schema-extractor.js.map +1 -0
  211. package/dist/core/analyzer/signature-extractor.d.ts +31 -0
  212. package/dist/core/analyzer/signature-extractor.d.ts.map +1 -0
  213. package/dist/core/analyzer/signature-extractor.js +675 -0
  214. package/dist/core/analyzer/signature-extractor.js.map +1 -0
  215. package/dist/core/analyzer/significance-scorer.d.ts +79 -0
  216. package/dist/core/analyzer/significance-scorer.d.ts.map +1 -0
  217. package/dist/core/analyzer/significance-scorer.js +407 -0
  218. package/dist/core/analyzer/significance-scorer.js.map +1 -0
  219. package/dist/core/analyzer/spec-snapshot-generator.d.ts +17 -0
  220. package/dist/core/analyzer/spec-snapshot-generator.d.ts.map +1 -0
  221. package/dist/core/analyzer/spec-snapshot-generator.js +201 -0
  222. package/dist/core/analyzer/spec-snapshot-generator.js.map +1 -0
  223. package/dist/core/analyzer/spec-vector-index.d.ts +68 -0
  224. package/dist/core/analyzer/spec-vector-index.d.ts.map +1 -0
  225. package/dist/core/analyzer/spec-vector-index.js +340 -0
  226. package/dist/core/analyzer/spec-vector-index.js.map +1 -0
  227. package/dist/core/analyzer/subgraph-extractor.d.ts +51 -0
  228. package/dist/core/analyzer/subgraph-extractor.d.ts.map +1 -0
  229. package/dist/core/analyzer/subgraph-extractor.js +147 -0
  230. package/dist/core/analyzer/subgraph-extractor.js.map +1 -0
  231. package/dist/core/analyzer/type-inference-engine.d.ts +23 -0
  232. package/dist/core/analyzer/type-inference-engine.d.ts.map +1 -0
  233. package/dist/core/analyzer/type-inference-engine.js +130 -0
  234. package/dist/core/analyzer/type-inference-engine.js.map +1 -0
  235. package/dist/core/analyzer/ui-component-extractor.d.ts +43 -0
  236. package/dist/core/analyzer/ui-component-extractor.d.ts.map +1 -0
  237. package/dist/core/analyzer/ui-component-extractor.js +245 -0
  238. package/dist/core/analyzer/ui-component-extractor.js.map +1 -0
  239. package/dist/core/analyzer/unified-search.d.ts +116 -0
  240. package/dist/core/analyzer/unified-search.d.ts.map +1 -0
  241. package/dist/core/analyzer/unified-search.js +231 -0
  242. package/dist/core/analyzer/unified-search.js.map +1 -0
  243. package/dist/core/analyzer/vector-index.d.ts +92 -0
  244. package/dist/core/analyzer/vector-index.d.ts.map +1 -0
  245. package/dist/core/analyzer/vector-index.js +451 -0
  246. package/dist/core/analyzer/vector-index.js.map +1 -0
  247. package/dist/core/decisions/consolidator.d.ts +14 -0
  248. package/dist/core/decisions/consolidator.d.ts.map +1 -0
  249. package/dist/core/decisions/consolidator.js +169 -0
  250. package/dist/core/decisions/consolidator.js.map +1 -0
  251. package/dist/core/decisions/extractor.d.ts +26 -0
  252. package/dist/core/decisions/extractor.d.ts.map +1 -0
  253. package/dist/core/decisions/extractor.js +156 -0
  254. package/dist/core/decisions/extractor.js.map +1 -0
  255. package/dist/core/decisions/index.d.ts +19 -0
  256. package/dist/core/decisions/index.d.ts.map +1 -0
  257. package/dist/core/decisions/index.js +16 -0
  258. package/dist/core/decisions/index.js.map +1 -0
  259. package/dist/core/decisions/store.d.ts +36 -0
  260. package/dist/core/decisions/store.d.ts.map +1 -0
  261. package/dist/core/decisions/store.js +109 -0
  262. package/dist/core/decisions/store.js.map +1 -0
  263. package/dist/core/decisions/syncer.d.ts +27 -0
  264. package/dist/core/decisions/syncer.d.ts.map +1 -0
  265. package/dist/core/decisions/syncer.js +214 -0
  266. package/dist/core/decisions/syncer.js.map +1 -0
  267. package/dist/core/decisions/verifier.d.ts +20 -0
  268. package/dist/core/decisions/verifier.d.ts.map +1 -0
  269. package/dist/core/decisions/verifier.js +115 -0
  270. package/dist/core/decisions/verifier.js.map +1 -0
  271. package/dist/core/digest/digest-generator.d.ts +29 -0
  272. package/dist/core/digest/digest-generator.d.ts.map +1 -0
  273. package/dist/core/digest/digest-generator.js +181 -0
  274. package/dist/core/digest/digest-generator.js.map +1 -0
  275. package/dist/core/drift/drift-detector.d.ts +102 -0
  276. package/dist/core/drift/drift-detector.d.ts.map +1 -0
  277. package/dist/core/drift/drift-detector.js +598 -0
  278. package/dist/core/drift/drift-detector.js.map +1 -0
  279. package/dist/core/drift/git-diff.d.ts +60 -0
  280. package/dist/core/drift/git-diff.d.ts.map +1 -0
  281. package/dist/core/drift/git-diff.js +383 -0
  282. package/dist/core/drift/git-diff.js.map +1 -0
  283. package/dist/core/drift/index.d.ts +12 -0
  284. package/dist/core/drift/index.d.ts.map +1 -0
  285. package/dist/core/drift/index.js +9 -0
  286. package/dist/core/drift/index.js.map +1 -0
  287. package/dist/core/drift/spec-mapper.d.ts +73 -0
  288. package/dist/core/drift/spec-mapper.d.ts.map +1 -0
  289. package/dist/core/drift/spec-mapper.js +353 -0
  290. package/dist/core/drift/spec-mapper.js.map +1 -0
  291. package/dist/core/drift/test-suggester.d.ts +18 -0
  292. package/dist/core/drift/test-suggester.d.ts.map +1 -0
  293. package/dist/core/drift/test-suggester.js +107 -0
  294. package/dist/core/drift/test-suggester.js.map +1 -0
  295. package/dist/core/generator/adr-generator.d.ts +32 -0
  296. package/dist/core/generator/adr-generator.d.ts.map +1 -0
  297. package/dist/core/generator/adr-generator.js +192 -0
  298. package/dist/core/generator/adr-generator.js.map +1 -0
  299. package/dist/core/generator/index.d.ts +9 -0
  300. package/dist/core/generator/index.d.ts.map +1 -0
  301. package/dist/core/generator/index.js +12 -0
  302. package/dist/core/generator/index.js.map +1 -0
  303. package/dist/core/generator/mapping-generator.d.ts +54 -0
  304. package/dist/core/generator/mapping-generator.d.ts.map +1 -0
  305. package/dist/core/generator/mapping-generator.js +240 -0
  306. package/dist/core/generator/mapping-generator.js.map +1 -0
  307. package/dist/core/generator/openspec-compat.d.ts +160 -0
  308. package/dist/core/generator/openspec-compat.d.ts.map +1 -0
  309. package/dist/core/generator/openspec-compat.js +524 -0
  310. package/dist/core/generator/openspec-compat.js.map +1 -0
  311. package/dist/core/generator/openspec-format-generator.d.ts +131 -0
  312. package/dist/core/generator/openspec-format-generator.d.ts.map +1 -0
  313. package/dist/core/generator/openspec-format-generator.js +963 -0
  314. package/dist/core/generator/openspec-format-generator.js.map +1 -0
  315. package/dist/core/generator/openspec-writer.d.ts +130 -0
  316. package/dist/core/generator/openspec-writer.d.ts.map +1 -0
  317. package/dist/core/generator/openspec-writer.js +404 -0
  318. package/dist/core/generator/openspec-writer.js.map +1 -0
  319. package/dist/core/generator/prompts.d.ts +35 -0
  320. package/dist/core/generator/prompts.d.ts.map +1 -0
  321. package/dist/core/generator/prompts.js +212 -0
  322. package/dist/core/generator/prompts.js.map +1 -0
  323. package/dist/core/generator/rag-manifest-generator.d.ts +37 -0
  324. package/dist/core/generator/rag-manifest-generator.d.ts.map +1 -0
  325. package/dist/core/generator/rag-manifest-generator.js +134 -0
  326. package/dist/core/generator/rag-manifest-generator.js.map +1 -0
  327. package/dist/core/generator/schemas.d.ts +365 -0
  328. package/dist/core/generator/schemas.d.ts.map +1 -0
  329. package/dist/core/generator/schemas.js +190 -0
  330. package/dist/core/generator/schemas.js.map +1 -0
  331. package/dist/core/generator/spec-pipeline.d.ts +123 -0
  332. package/dist/core/generator/spec-pipeline.d.ts.map +1 -0
  333. package/dist/core/generator/spec-pipeline.js +699 -0
  334. package/dist/core/generator/spec-pipeline.js.map +1 -0
  335. package/dist/core/generator/stages/stage1-survey.d.ts +19 -0
  336. package/dist/core/generator/stages/stage1-survey.d.ts.map +1 -0
  337. package/dist/core/generator/stages/stage1-survey.js +171 -0
  338. package/dist/core/generator/stages/stage1-survey.js.map +1 -0
  339. package/dist/core/generator/stages/stage2-entities.d.ts +11 -0
  340. package/dist/core/generator/stages/stage2-entities.d.ts.map +1 -0
  341. package/dist/core/generator/stages/stage2-entities.js +74 -0
  342. package/dist/core/generator/stages/stage2-entities.js.map +1 -0
  343. package/dist/core/generator/stages/stage3-services.d.ts +11 -0
  344. package/dist/core/generator/stages/stage3-services.d.ts.map +1 -0
  345. package/dist/core/generator/stages/stage3-services.js +85 -0
  346. package/dist/core/generator/stages/stage3-services.js.map +1 -0
  347. package/dist/core/generator/stages/stage4-api.d.ts +11 -0
  348. package/dist/core/generator/stages/stage4-api.d.ts.map +1 -0
  349. package/dist/core/generator/stages/stage4-api.js +72 -0
  350. package/dist/core/generator/stages/stage4-api.js.map +1 -0
  351. package/dist/core/generator/stages/stage5-architecture.d.ts +11 -0
  352. package/dist/core/generator/stages/stage5-architecture.d.ts.map +1 -0
  353. package/dist/core/generator/stages/stage5-architecture.js +75 -0
  354. package/dist/core/generator/stages/stage5-architecture.js.map +1 -0
  355. package/dist/core/generator/stages/stage6-adr.d.ts +8 -0
  356. package/dist/core/generator/stages/stage6-adr.d.ts.map +1 -0
  357. package/dist/core/generator/stages/stage6-adr.js +47 -0
  358. package/dist/core/generator/stages/stage6-adr.js.map +1 -0
  359. package/dist/core/services/chat-agent.d.ts +50 -0
  360. package/dist/core/services/chat-agent.d.ts.map +1 -0
  361. package/dist/core/services/chat-agent.js +369 -0
  362. package/dist/core/services/chat-agent.js.map +1 -0
  363. package/dist/core/services/chat-tools.d.ts +32 -0
  364. package/dist/core/services/chat-tools.d.ts.map +1 -0
  365. package/dist/core/services/chat-tools.js +494 -0
  366. package/dist/core/services/chat-tools.js.map +1 -0
  367. package/dist/core/services/config-manager.d.ts +61 -0
  368. package/dist/core/services/config-manager.d.ts.map +1 -0
  369. package/dist/core/services/config-manager.js +149 -0
  370. package/dist/core/services/config-manager.js.map +1 -0
  371. package/dist/core/services/edge-store.d.ts +57 -0
  372. package/dist/core/services/edge-store.d.ts.map +1 -0
  373. package/dist/core/services/edge-store.js +419 -0
  374. package/dist/core/services/edge-store.js.map +1 -0
  375. package/dist/core/services/gitignore-manager.d.ts +29 -0
  376. package/dist/core/services/gitignore-manager.d.ts.map +1 -0
  377. package/dist/core/services/gitignore-manager.js +95 -0
  378. package/dist/core/services/gitignore-manager.js.map +1 -0
  379. package/dist/core/services/index.d.ts +8 -0
  380. package/dist/core/services/index.d.ts.map +1 -0
  381. package/dist/core/services/index.js +8 -0
  382. package/dist/core/services/index.js.map +1 -0
  383. package/dist/core/services/llm-service.d.ts +379 -0
  384. package/dist/core/services/llm-service.d.ts.map +1 -0
  385. package/dist/core/services/llm-service.js +1553 -0
  386. package/dist/core/services/llm-service.js.map +1 -0
  387. package/dist/core/services/mcp-handlers/analysis.d.ts +127 -0
  388. package/dist/core/services/mcp-handlers/analysis.d.ts.map +1 -0
  389. package/dist/core/services/mcp-handlers/analysis.js +1185 -0
  390. package/dist/core/services/mcp-handlers/analysis.js.map +1 -0
  391. package/dist/core/services/mcp-handlers/change.d.ts +14 -0
  392. package/dist/core/services/mcp-handlers/change.d.ts.map +1 -0
  393. package/dist/core/services/mcp-handlers/change.js +416 -0
  394. package/dist/core/services/mcp-handlers/change.js.map +1 -0
  395. package/dist/core/services/mcp-handlers/decisions.d.ts +16 -0
  396. package/dist/core/services/mcp-handlers/decisions.d.ts.map +1 -0
  397. package/dist/core/services/mcp-handlers/decisions.js +239 -0
  398. package/dist/core/services/mcp-handlers/decisions.js.map +1 -0
  399. package/dist/core/services/mcp-handlers/graph.d.ts +94 -0
  400. package/dist/core/services/mcp-handlers/graph.d.ts.map +1 -0
  401. package/dist/core/services/mcp-handlers/graph.js +693 -0
  402. package/dist/core/services/mcp-handlers/graph.js.map +1 -0
  403. package/dist/core/services/mcp-handlers/orient.d.ts +17 -0
  404. package/dist/core/services/mcp-handlers/orient.d.ts.map +1 -0
  405. package/dist/core/services/mcp-handlers/orient.js +357 -0
  406. package/dist/core/services/mcp-handlers/orient.js.map +1 -0
  407. package/dist/core/services/mcp-handlers/semantic.d.ts +66 -0
  408. package/dist/core/services/mcp-handlers/semantic.d.ts.map +1 -0
  409. package/dist/core/services/mcp-handlers/semantic.js +432 -0
  410. package/dist/core/services/mcp-handlers/semantic.js.map +1 -0
  411. package/dist/core/services/mcp-handlers/utils.d.ts +85 -0
  412. package/dist/core/services/mcp-handlers/utils.d.ts.map +1 -0
  413. package/dist/core/services/mcp-handlers/utils.js +262 -0
  414. package/dist/core/services/mcp-handlers/utils.js.map +1 -0
  415. package/dist/core/services/mcp-watcher.d.ts +41 -0
  416. package/dist/core/services/mcp-watcher.d.ts.map +1 -0
  417. package/dist/core/services/mcp-watcher.js +254 -0
  418. package/dist/core/services/mcp-watcher.js.map +1 -0
  419. package/dist/core/services/project-detector.d.ts +32 -0
  420. package/dist/core/services/project-detector.d.ts.map +1 -0
  421. package/dist/core/services/project-detector.js +100 -0
  422. package/dist/core/services/project-detector.js.map +1 -0
  423. package/dist/core/test-generator/coverage-analyzer.d.ts +27 -0
  424. package/dist/core/test-generator/coverage-analyzer.d.ts.map +1 -0
  425. package/dist/core/test-generator/coverage-analyzer.js +285 -0
  426. package/dist/core/test-generator/coverage-analyzer.js.map +1 -0
  427. package/dist/core/test-generator/framework-detector.d.ts +17 -0
  428. package/dist/core/test-generator/framework-detector.d.ts.map +1 -0
  429. package/dist/core/test-generator/framework-detector.js +65 -0
  430. package/dist/core/test-generator/framework-detector.js.map +1 -0
  431. package/dist/core/test-generator/index.d.ts +14 -0
  432. package/dist/core/test-generator/index.d.ts.map +1 -0
  433. package/dist/core/test-generator/index.js +11 -0
  434. package/dist/core/test-generator/index.js.map +1 -0
  435. package/dist/core/test-generator/renderers/catch2.d.ts +8 -0
  436. package/dist/core/test-generator/renderers/catch2.d.ts.map +1 -0
  437. package/dist/core/test-generator/renderers/catch2.js +47 -0
  438. package/dist/core/test-generator/renderers/catch2.js.map +1 -0
  439. package/dist/core/test-generator/renderers/gtest.d.ts +8 -0
  440. package/dist/core/test-generator/renderers/gtest.d.ts.map +1 -0
  441. package/dist/core/test-generator/renderers/gtest.js +45 -0
  442. package/dist/core/test-generator/renderers/gtest.js.map +1 -0
  443. package/dist/core/test-generator/renderers/index.d.ts +20 -0
  444. package/dist/core/test-generator/renderers/index.d.ts.map +1 -0
  445. package/dist/core/test-generator/renderers/index.js +35 -0
  446. package/dist/core/test-generator/renderers/index.js.map +1 -0
  447. package/dist/core/test-generator/renderers/playwright.d.ts +8 -0
  448. package/dist/core/test-generator/renderers/playwright.d.ts.map +1 -0
  449. package/dist/core/test-generator/renderers/playwright.js +44 -0
  450. package/dist/core/test-generator/renderers/playwright.js.map +1 -0
  451. package/dist/core/test-generator/renderers/pytest.d.ts +8 -0
  452. package/dist/core/test-generator/renderers/pytest.d.ts.map +1 -0
  453. package/dist/core/test-generator/renderers/pytest.js +44 -0
  454. package/dist/core/test-generator/renderers/pytest.js.map +1 -0
  455. package/dist/core/test-generator/renderers/shared.d.ts +21 -0
  456. package/dist/core/test-generator/renderers/shared.d.ts.map +1 -0
  457. package/dist/core/test-generator/renderers/shared.js +56 -0
  458. package/dist/core/test-generator/renderers/shared.js.map +1 -0
  459. package/dist/core/test-generator/renderers/vitest.d.ts +8 -0
  460. package/dist/core/test-generator/renderers/vitest.d.ts.map +1 -0
  461. package/dist/core/test-generator/renderers/vitest.js +52 -0
  462. package/dist/core/test-generator/renderers/vitest.js.map +1 -0
  463. package/dist/core/test-generator/scenario-parser.d.ts +33 -0
  464. package/dist/core/test-generator/scenario-parser.d.ts.map +1 -0
  465. package/dist/core/test-generator/scenario-parser.js +244 -0
  466. package/dist/core/test-generator/scenario-parser.js.map +1 -0
  467. package/dist/core/test-generator/test-generator.d.ts +30 -0
  468. package/dist/core/test-generator/test-generator.d.ts.map +1 -0
  469. package/dist/core/test-generator/test-generator.js +174 -0
  470. package/dist/core/test-generator/test-generator.js.map +1 -0
  471. package/dist/core/test-generator/test-writer.d.ts +25 -0
  472. package/dist/core/test-generator/test-writer.d.ts.map +1 -0
  473. package/dist/core/test-generator/test-writer.js +128 -0
  474. package/dist/core/test-generator/test-writer.js.map +1 -0
  475. package/dist/core/test-generator/then-matchers.d.ts +35 -0
  476. package/dist/core/test-generator/then-matchers.d.ts.map +1 -0
  477. package/dist/core/test-generator/then-matchers.js +211 -0
  478. package/dist/core/test-generator/then-matchers.js.map +1 -0
  479. package/dist/core/verifier/index.d.ts +5 -0
  480. package/dist/core/verifier/index.d.ts.map +1 -0
  481. package/dist/core/verifier/index.js +5 -0
  482. package/dist/core/verifier/index.js.map +1 -0
  483. package/dist/core/verifier/verification-engine.d.ts +293 -0
  484. package/dist/core/verifier/verification-engine.d.ts.map +1 -0
  485. package/dist/core/verifier/verification-engine.js +919 -0
  486. package/dist/core/verifier/verification-engine.js.map +1 -0
  487. package/dist/types/index.d.ts +368 -0
  488. package/dist/types/index.d.ts.map +1 -0
  489. package/dist/types/index.js +5 -0
  490. package/dist/types/index.js.map +1 -0
  491. package/dist/types/pipeline.d.ts +167 -0
  492. package/dist/types/pipeline.d.ts.map +1 -0
  493. package/dist/types/pipeline.js +5 -0
  494. package/dist/types/pipeline.js.map +1 -0
  495. package/dist/types/test-generator.d.ts +103 -0
  496. package/dist/types/test-generator.d.ts.map +1 -0
  497. package/dist/types/test-generator.js +17 -0
  498. package/dist/types/test-generator.js.map +1 -0
  499. package/dist/utils/command-helpers.d.ts +68 -0
  500. package/dist/utils/command-helpers.d.ts.map +1 -0
  501. package/dist/utils/command-helpers.js +150 -0
  502. package/dist/utils/command-helpers.js.map +1 -0
  503. package/dist/utils/errors.d.ts +51 -0
  504. package/dist/utils/errors.d.ts.map +1 -0
  505. package/dist/utils/errors.js +129 -0
  506. package/dist/utils/errors.js.map +1 -0
  507. package/dist/utils/logger.d.ts +149 -0
  508. package/dist/utils/logger.d.ts.map +1 -0
  509. package/dist/utils/logger.js +342 -0
  510. package/dist/utils/logger.js.map +1 -0
  511. package/dist/utils/misc.d.ts +10 -0
  512. package/dist/utils/misc.d.ts.map +1 -0
  513. package/dist/utils/misc.js +21 -0
  514. package/dist/utils/misc.js.map +1 -0
  515. package/dist/utils/progress.d.ts +142 -0
  516. package/dist/utils/progress.d.ts.map +1 -0
  517. package/dist/utils/progress.js +283 -0
  518. package/dist/utils/progress.js.map +1 -0
  519. package/dist/utils/prompts.d.ts +53 -0
  520. package/dist/utils/prompts.d.ts.map +1 -0
  521. package/dist/utils/prompts.js +199 -0
  522. package/dist/utils/prompts.js.map +1 -0
  523. package/dist/utils/shutdown.d.ts +89 -0
  524. package/dist/utils/shutdown.d.ts.map +1 -0
  525. package/dist/utils/shutdown.js +238 -0
  526. package/dist/utils/shutdown.js.map +1 -0
  527. package/examples/bmad/README.md +113 -0
  528. package/examples/bmad/agents/architect.md +226 -0
  529. package/examples/bmad/agents/dev-brownfield.md +69 -0
  530. package/examples/bmad/setup/architect.customize.yaml +14 -0
  531. package/examples/bmad/tasks/implement-story.md +254 -0
  532. package/examples/bmad/tasks/onboarding.md +169 -0
  533. package/examples/bmad/tasks/refactor.md +178 -0
  534. package/examples/bmad/tasks/sprint-planning.md +168 -0
  535. package/examples/bmad/templates/story.md +108 -0
  536. package/examples/cline-workflows/openlore-analyze-codebase.md +101 -0
  537. package/examples/cline-workflows/openlore-check-spec-drift.md +102 -0
  538. package/examples/cline-workflows/openlore-execute-refactor.md +212 -0
  539. package/examples/cline-workflows/openlore-implement-feature.md +266 -0
  540. package/examples/cline-workflows/openlore-plan-refactor.md +279 -0
  541. package/examples/cline-workflows/openlore-refactor-codebase.md +16 -0
  542. package/examples/cline-workflows/openlore-write-tests.md +177 -0
  543. package/examples/drift-demo/openspec/config.yaml +14 -0
  544. package/examples/drift-demo/openspec/specs/architecture/spec.md +30 -0
  545. package/examples/drift-demo/openspec/specs/auth/spec.md +71 -0
  546. package/examples/drift-demo/openspec/specs/database/spec.md +33 -0
  547. package/examples/drift-demo/openspec/specs/overview/spec.md +20 -0
  548. package/examples/drift-demo/openspec/specs/projects/spec.md +55 -0
  549. package/examples/drift-demo/openspec/specs/tasks/spec.md +78 -0
  550. package/examples/drift-demo/package.json +21 -0
  551. package/examples/drift-demo/src/auth/auth-middleware.ts +30 -0
  552. package/examples/drift-demo/src/auth/auth-routes.ts +29 -0
  553. package/examples/drift-demo/src/auth/auth-service.ts +45 -0
  554. package/examples/drift-demo/src/database/connection.ts +27 -0
  555. package/examples/drift-demo/src/index.ts +16 -0
  556. package/examples/drift-demo/src/projects/project-model.ts +15 -0
  557. package/examples/drift-demo/src/projects/project-service.ts +34 -0
  558. package/examples/drift-demo/src/tasks/task-model.ts +37 -0
  559. package/examples/drift-demo/src/tasks/task-routes.ts +53 -0
  560. package/examples/drift-demo/src/tasks/task-service.ts +60 -0
  561. package/examples/drift-demo/src/utils/validation.ts +11 -0
  562. package/examples/drift-demo/tests/auth.test.ts +4 -0
  563. package/examples/drift-demo/tests/tasks.test.ts +4 -0
  564. package/examples/drift-demo/tsconfig.json +10 -0
  565. package/examples/drift-test/run-drift-test.sh +1087 -0
  566. package/examples/gsd/README.md +119 -0
  567. package/examples/gsd/commands/gsd/openlore-drift.md +111 -0
  568. package/examples/gsd/commands/gsd/openlore-orient.md +191 -0
  569. package/examples/mistral-vibe/README.md +101 -0
  570. package/examples/mistral-vibe/antipatterns-template.md +18 -0
  571. package/examples/mistral-vibe/skills/openlore-analyze-codebase/SKILL.md +124 -0
  572. package/examples/mistral-vibe/skills/openlore-brainstorm/SKILL.md +379 -0
  573. package/examples/mistral-vibe/skills/openlore-debug/SKILL.md +330 -0
  574. package/examples/mistral-vibe/skills/openlore-execute-refactor/SKILL.md +291 -0
  575. package/examples/mistral-vibe/skills/openlore-generate/SKILL.md +245 -0
  576. package/examples/mistral-vibe/skills/openlore-implement-story/SKILL.md +326 -0
  577. package/examples/mistral-vibe/skills/openlore-plan-refactor/SKILL.md +365 -0
  578. package/examples/mistral-vibe/skills/openlore-review-changes/SKILL.md +128 -0
  579. package/examples/mistral-vibe/skills/openlore-write-tests/SKILL.md +261 -0
  580. package/examples/opencode/agent-guard.ts +170 -0
  581. package/examples/opencode/plugins/anti-laziness.ts +202 -0
  582. package/examples/opencode/plugins/lib/openlore-context-injector-helpers.ts +116 -0
  583. package/examples/opencode/plugins/lib/openlore-decision-extractor-helpers.ts +65 -0
  584. package/examples/opencode/plugins/openlore-context-injector.test.ts +211 -0
  585. package/examples/opencode/plugins/openlore-context-injector.ts +165 -0
  586. package/examples/opencode/plugins/openlore-decision-extractor.test.ts +131 -0
  587. package/examples/opencode/plugins/openlore-decision-extractor.ts +322 -0
  588. package/examples/opencode/plugins/openlore-enforcer.ts +227 -0
  589. package/examples/opencode/prompts/sisyphus-sdd.md +150 -0
  590. package/examples/opencode-skills/openlore-analyze-codebase/SKILL.md +101 -0
  591. package/examples/opencode-skills/openlore-brainstorm/SKILL.md +354 -0
  592. package/examples/opencode-skills/openlore-debug/SKILL.md +291 -0
  593. package/examples/opencode-skills/openlore-execute-refactor/SKILL.md +241 -0
  594. package/examples/opencode-skills/openlore-generate/SKILL.md +236 -0
  595. package/examples/opencode-skills/openlore-implement-story/SKILL.md +251 -0
  596. package/examples/opencode-skills/openlore-plan-refactor/SKILL.md +298 -0
  597. package/examples/opencode-skills/openlore-review-changes/SKILL.md +134 -0
  598. package/examples/opencode-skills/openlore-write-tests/SKILL.md +230 -0
  599. package/examples/openspec-analysis/README.md +59 -0
  600. package/examples/openspec-analysis/SUMMARY.md +72 -0
  601. package/examples/openspec-analysis/config.json +16 -0
  602. package/examples/openspec-analysis/dependencies.mermaid +35 -0
  603. package/examples/openspec-analysis/dependency-graph.json +12116 -0
  604. package/examples/openspec-analysis/llm-context.json +119 -0
  605. package/examples/openspec-analysis/repo-structure.json +871 -0
  606. package/examples/openspec-cli/README.md +67 -0
  607. package/examples/openspec-cli/openspec/config.yaml +26 -0
  608. package/examples/openspec-cli/openspec/specs/architecture/spec.md +178 -0
  609. package/examples/openspec-cli/openspec/specs/artifact-graph/spec.md +143 -0
  610. package/examples/openspec-cli/openspec/specs/cli/spec.md +138 -0
  611. package/examples/openspec-cli/openspec/specs/overview/spec.md +60 -0
  612. package/examples/openspec-cli/openspec/specs/parsing/spec.md +123 -0
  613. package/examples/openspec-cli/openspec/specs/validation/spec.md +108 -0
  614. package/examples/spec-kit/README.md +104 -0
  615. package/examples/spec-kit/commands/drift.md +87 -0
  616. package/examples/spec-kit/commands/orient.md +138 -0
  617. package/examples/spec-kit/extension.yml +54 -0
  618. package/package.json +125 -0
  619. package/src/viewer/InteractiveGraphViewer.jsx +1600 -0
  620. package/src/viewer/app/index.html +17 -0
  621. package/src/viewer/app/main.jsx +13 -0
  622. package/src/viewer/components/ArchitectureView.jsx +177 -0
  623. package/src/viewer/components/ChatPanel.jsx +450 -0
  624. package/src/viewer/components/ClassGraph.jsx +782 -0
  625. package/src/viewer/components/ClusterGraph.jsx +469 -0
  626. package/src/viewer/components/FilterBar.jsx +179 -0
  627. package/src/viewer/components/FlatGraph.jsx +282 -0
  628. package/src/viewer/components/MicroComponents.jsx +85 -0
  629. package/src/viewer/hooks/usePanZoom.js +79 -0
  630. package/src/viewer/utils/constants.js +64 -0
  631. package/src/viewer/utils/graph-helpers.js +303 -0
  632. package/src/viewer/utils/graph-helpers.test.ts +39 -0
  633. package/src/viewer/utils/themes.js +206 -0
  634. package/stubs/tree-sitter-cli-stub/package.json +6 -0
@@ -0,0 +1,752 @@
1
+ /**
2
+ * Dependency Graph Service
3
+ *
4
+ * Builds a complete graph of how files relate to each other through imports.
5
+ * Provides metrics like in-degree, out-degree, betweenness centrality, and PageRank.
6
+ * Detects clusters, cycles, and special nodes (centers, leaves, bridges, orphans).
7
+ */
8
+ import { ImportExportParser, resolveImport } from './import-parser.js';
9
+ import { extractAllHttpEdges } from './http-route-parser.js';
10
+ // ============================================================================
11
+ // CONSTANTS
12
+ // ============================================================================
13
+ const CLUSTER_PALETTE = [
14
+ '#7c6af7',
15
+ '#3ecfcf',
16
+ '#f77c6a',
17
+ '#6af7a0',
18
+ '#f7c76a',
19
+ '#f76ac8',
20
+ '#6aaff7',
21
+ '#c8f76a',
22
+ '#f7a06a',
23
+ '#a0a0ff',
24
+ '#ff6b9d',
25
+ '#00d4aa',
26
+ '#ffb347',
27
+ ];
28
+ // ============================================================================
29
+ // DEPENDENCY GRAPH BUILDER
30
+ // ============================================================================
31
+ /**
32
+ * Builds and analyzes a dependency graph from scored files
33
+ */
34
+ export class DependencyGraphBuilder {
35
+ nodes = new Map();
36
+ edges = [];
37
+ adjacencyList = new Map();
38
+ reverseAdjacencyList = new Map();
39
+ httpEdgeCount = 0;
40
+ parser;
41
+ options;
42
+ constructor(options) {
43
+ this.parser = new ImportExportParser();
44
+ this.options = {
45
+ rootDir: options.rootDir,
46
+ extensions: options.extensions ?? [], // empty = auto-detect per file in resolveImport
47
+ minClusterSize: options.minClusterSize ?? 2,
48
+ dampingFactor: options.dampingFactor ?? 0.85,
49
+ maxIterations: options.maxIterations ?? 100,
50
+ };
51
+ }
52
+ /**
53
+ * Build the dependency graph from scored files
54
+ */
55
+ async build(files) {
56
+ // Clear any previous state
57
+ this.nodes.clear();
58
+ this.edges = [];
59
+ this.adjacencyList.clear();
60
+ this.reverseAdjacencyList.clear();
61
+ this.httpEdgeCount = 0;
62
+ // Parse all files and create nodes
63
+ const analyses = await this.parseFiles(files);
64
+ // Create nodes for each file
65
+ for (const file of files) {
66
+ const analysis = analyses.get(file.absolutePath);
67
+ this.nodes.set(file.absolutePath, {
68
+ id: file.absolutePath,
69
+ file,
70
+ exports: analysis?.exports ?? [],
71
+ metrics: {
72
+ inDegree: 0,
73
+ outDegree: 0,
74
+ betweenness: 0,
75
+ pageRank: 1 / files.length,
76
+ },
77
+ });
78
+ this.adjacencyList.set(file.absolutePath, new Set());
79
+ this.reverseAdjacencyList.set(file.absolutePath, new Set());
80
+ }
81
+ // Create edges from imports
82
+ await this.buildEdges(files, analyses);
83
+ // Create cross-language edges from HTTP calls (fetch/axios → FastAPI routes)
84
+ await this.buildHttpCrossEdges(files);
85
+ // Calculate metrics
86
+ this.calculateDegrees();
87
+ this.calculateBetweenness();
88
+ this.calculatePageRank();
89
+ // Detect clusters
90
+ const clusters = this.detectClusters();
91
+ // Assign clusters to nodes
92
+ const clusterByNode = {};
93
+ clusters.forEach((cl) => {
94
+ cl.files.forEach((fid) => {
95
+ clusterByNode[fid] = { id: cl.id, name: cl.name, color: cl.color };
96
+ });
97
+ });
98
+ for (const [id, node] of this.nodes) {
99
+ node.cluster = clusterByNode[id];
100
+ }
101
+ // Detect cycles
102
+ const cycles = this.detectCycles();
103
+ // Generate rankings
104
+ const rankings = this.generateRankings(clusters);
105
+ // Calculate statistics
106
+ const statistics = this.calculateStatistics(clusters, cycles);
107
+ const structuralClusters = clusters.filter(c => c.isStructural);
108
+ return {
109
+ nodes: Array.from(this.nodes.values()),
110
+ edges: this.edges,
111
+ clusters,
112
+ structuralClusters,
113
+ rankings,
114
+ cycles,
115
+ statistics,
116
+ };
117
+ }
118
+ /**
119
+ * Parse all files to extract imports/exports
120
+ */
121
+ async parseFiles(files) {
122
+ const analyses = new Map();
123
+ for (const file of files) {
124
+ try {
125
+ const analysis = await this.parser.parseFile(file.absolutePath);
126
+ analyses.set(file.absolutePath, analysis);
127
+ }
128
+ catch (error) {
129
+ // File couldn't be parsed (binary, syntax error, etc.) — skip it
130
+ if (process.env.DEBUG) {
131
+ console.debug(`[dep-graph] Failed to parse ${file.absolutePath}: ${error.message}`);
132
+ }
133
+ }
134
+ }
135
+ return analyses;
136
+ }
137
+ /**
138
+ * Build cross-language edges by matching HTTP calls in JS/TS files to
139
+ * FastAPI/Flask/Django route definitions in Python files.
140
+ * Only creates edges between files that are already nodes in the graph.
141
+ */
142
+ async buildHttpCrossEdges(files) {
143
+ const fileSet = new Set(files.map(f => f.absolutePath));
144
+ const filePaths = Array.from(fileSet);
145
+ // Skip HTTP edge detection entirely when there cannot be any cross-language
146
+ // edges: we need at least one caller file AND at least one handler file.
147
+ // Callers are JS/TS. Handlers can be Python, Java, or TS/JS (server-side).
148
+ const jsExts = new Set(['.js', '.jsx', '.ts', '.tsx', '.mjs', '.cjs']);
149
+ const pyExts = new Set(['.py', '.pyw']);
150
+ const hasJs = filePaths.some(fp => jsExts.has(fp.slice(fp.lastIndexOf('.')).toLowerCase()));
151
+ const hasHandler = filePaths.some(fp => {
152
+ const ext = fp.slice(fp.lastIndexOf('.')).toLowerCase();
153
+ return pyExts.has(ext) || ext === '.java';
154
+ });
155
+ if (!hasJs || !hasHandler)
156
+ return;
157
+ const { edges: httpEdges } = await extractAllHttpEdges(filePaths);
158
+ for (const httpEdge of httpEdges) {
159
+ // Both ends must be known nodes
160
+ if (!fileSet.has(httpEdge.callerFile) || !fileSet.has(httpEdge.handlerFile))
161
+ continue;
162
+ // Skip self-loops
163
+ if (httpEdge.callerFile === httpEdge.handlerFile)
164
+ continue;
165
+ // Weight by confidence: exact=1.0, path=0.75, fuzzy=0.5
166
+ const weight = httpEdge.confidence === 'exact' ? 1.0 :
167
+ httpEdge.confidence === 'path' ? 0.75 : 0.5;
168
+ const edge = {
169
+ source: httpEdge.callerFile,
170
+ target: httpEdge.handlerFile,
171
+ importedNames: [httpEdge.route.handlerName],
172
+ isTypeOnly: false,
173
+ weight,
174
+ httpEdge,
175
+ };
176
+ this.edges.push(edge);
177
+ this.httpEdgeCount++;
178
+ this.adjacencyList.get(httpEdge.callerFile)?.add(httpEdge.handlerFile);
179
+ this.reverseAdjacencyList.get(httpEdge.handlerFile)?.add(httpEdge.callerFile);
180
+ }
181
+ }
182
+ /**
183
+ * Build edges from import relationships
184
+ */
185
+ async buildEdges(files, analyses) {
186
+ const fileSet = new Set(files.map(f => f.absolutePath));
187
+ for (const file of files) {
188
+ const analysis = analyses.get(file.absolutePath);
189
+ if (!analysis)
190
+ continue;
191
+ const isPythonFile = file.absolutePath.endsWith('.py') || file.absolutePath.endsWith('.pyw');
192
+ const isJavaFile = file.absolutePath.endsWith('.java');
193
+ for (const imp of analysis.imports) {
194
+ // Skip non-relative imports for JS/TS (those are always npm packages).
195
+ // For Python files we must NOT skip: `from services.retriever import X`
196
+ // is flagged isRelative=false but may resolve to a local module.
197
+ // For Java files we also must NOT skip: imports are always absolute
198
+ // class FQNs and we try to resolve them against the project source root.
199
+ if (!imp.isRelative && !isPythonFile && !isJavaFile)
200
+ continue;
201
+ // Skip known builtins and third-party packages that can't resolve to
202
+ // a file inside the project (Python stdlib, JDK, Spring, etc.).
203
+ if (!imp.isRelative && imp.isBuiltin)
204
+ continue;
205
+ // Resolve the import to an absolute path
206
+ const resolvedPath = await resolveImport(imp.source, file.absolutePath, {
207
+ baseDir: this.options.rootDir,
208
+ extensions: this.options.extensions.length > 0 ? this.options.extensions : undefined,
209
+ sourcePackage: isJavaFile ? analysis.javaPackage : undefined,
210
+ });
211
+ // Skip if not resolved or not in our file set
212
+ if (!resolvedPath || !fileSet.has(resolvedPath))
213
+ continue;
214
+ // Create edge
215
+ const edge = {
216
+ source: file.absolutePath,
217
+ target: resolvedPath,
218
+ importedNames: imp.importedNames,
219
+ isTypeOnly: imp.isTypeOnly,
220
+ weight: imp.isTypeOnly ? 0.5 : 1,
221
+ };
222
+ this.edges.push(edge);
223
+ // Update adjacency lists
224
+ this.adjacencyList.get(file.absolutePath)?.add(resolvedPath);
225
+ this.reverseAdjacencyList.get(resolvedPath)?.add(file.absolutePath);
226
+ }
227
+ }
228
+ }
229
+ /**
230
+ * Calculate in-degree and out-degree for each node
231
+ */
232
+ calculateDegrees() {
233
+ for (const [nodeId, node] of this.nodes) {
234
+ node.metrics.outDegree = this.adjacencyList.get(nodeId)?.size ?? 0;
235
+ node.metrics.inDegree = this.reverseAdjacencyList.get(nodeId)?.size ?? 0;
236
+ }
237
+ }
238
+ /**
239
+ * Calculate betweenness centrality using Brandes' algorithm
240
+ */
241
+ calculateBetweenness() {
242
+ const nodeIds = Array.from(this.nodes.keys());
243
+ const betweenness = new Map();
244
+ // Initialize betweenness to 0
245
+ for (const id of nodeIds) {
246
+ betweenness.set(id, 0);
247
+ }
248
+ // Brandes' algorithm
249
+ for (const source of nodeIds) {
250
+ const stack = [];
251
+ const predecessors = new Map();
252
+ const sigma = new Map();
253
+ const distance = new Map();
254
+ const delta = new Map();
255
+ // Initialize
256
+ for (const v of nodeIds) {
257
+ predecessors.set(v, []);
258
+ sigma.set(v, 0);
259
+ distance.set(v, -1);
260
+ delta.set(v, 0);
261
+ }
262
+ sigma.set(source, 1);
263
+ distance.set(source, 0);
264
+ // BFS
265
+ const queue = [source];
266
+ while (queue.length > 0) {
267
+ const v = queue.shift();
268
+ stack.push(v);
269
+ const neighbors = this.adjacencyList.get(v) ?? new Set();
270
+ for (const w of neighbors) {
271
+ // First visit?
272
+ if (distance.get(w) < 0) {
273
+ queue.push(w);
274
+ distance.set(w, distance.get(v) + 1);
275
+ }
276
+ // Shortest path to w via v?
277
+ if (distance.get(w) === distance.get(v) + 1) {
278
+ sigma.set(w, sigma.get(w) + sigma.get(v));
279
+ predecessors.get(w).push(v);
280
+ }
281
+ }
282
+ }
283
+ // Back-propagation
284
+ while (stack.length > 0) {
285
+ const w = stack.pop();
286
+ for (const v of predecessors.get(w)) {
287
+ delta.set(v, delta.get(v) + (sigma.get(v) / sigma.get(w)) * (1 + delta.get(w)));
288
+ }
289
+ if (w !== source) {
290
+ betweenness.set(w, betweenness.get(w) + delta.get(w));
291
+ }
292
+ }
293
+ }
294
+ // Normalize and update nodes
295
+ const maxBetweenness = Array.from(betweenness.values()).reduce((a, b) => Math.max(a, b), 1);
296
+ for (const [nodeId, node] of this.nodes) {
297
+ node.metrics.betweenness = betweenness.get(nodeId) / maxBetweenness;
298
+ }
299
+ }
300
+ /**
301
+ * Calculate PageRank-style importance scores
302
+ */
303
+ calculatePageRank() {
304
+ const nodeIds = Array.from(this.nodes.keys());
305
+ const n = nodeIds.length;
306
+ if (n === 0)
307
+ return;
308
+ const d = this.options.dampingFactor;
309
+ let pageRank = new Map();
310
+ let newPageRank = new Map();
311
+ // Initialize
312
+ for (const id of nodeIds) {
313
+ pageRank.set(id, 1 / n);
314
+ }
315
+ // Iterate until convergence
316
+ for (let iter = 0; iter < this.options.maxIterations; iter++) {
317
+ let maxDiff = 0;
318
+ for (const id of nodeIds) {
319
+ // Sum contributions from nodes that link to this one
320
+ let sum = 0;
321
+ const incomingNodes = this.reverseAdjacencyList.get(id) ?? new Set();
322
+ for (const source of incomingNodes) {
323
+ const outDegree = this.adjacencyList.get(source)?.size ?? 1;
324
+ sum += pageRank.get(source) / outDegree;
325
+ }
326
+ const newRank = (1 - d) / n + d * sum;
327
+ newPageRank.set(id, newRank);
328
+ maxDiff = Math.max(maxDiff, Math.abs(newRank - pageRank.get(id)));
329
+ }
330
+ // Swap
331
+ [pageRank, newPageRank] = [newPageRank, pageRank];
332
+ // Check convergence
333
+ if (maxDiff < 1e-6)
334
+ break;
335
+ }
336
+ // Normalize and update nodes
337
+ const maxPageRank = Array.from(pageRank.values()).reduce((a, b) => Math.max(a, b), 0.001);
338
+ for (const [nodeId, node] of this.nodes) {
339
+ node.metrics.pageRank = pageRank.get(nodeId) / maxPageRank;
340
+ }
341
+ }
342
+ /**
343
+ * Detect clusters using a simple community detection approach
344
+ * Groups files by their common directory prefix and connectivity
345
+ */
346
+ detectClusters() {
347
+ const clusters = [];
348
+ const nodeIds = Array.from(this.nodes.keys());
349
+ // Group by directory
350
+ const dirGroups = new Map();
351
+ for (const nodeId of nodeIds) {
352
+ const node = this.nodes.get(nodeId);
353
+ const dir = node.file.directory || '(root)';
354
+ if (!dirGroups.has(dir)) {
355
+ dirGroups.set(dir, []);
356
+ }
357
+ dirGroups.get(dir).push(nodeId);
358
+ }
359
+ // Create clusters from directory groups
360
+ let clusterId = 0;
361
+ for (const [dir, files] of dirGroups) {
362
+ if (files.length < this.options.minClusterSize)
363
+ continue;
364
+ // Calculate internal and external edges
365
+ let internalEdges = 0;
366
+ let externalEdges = 0;
367
+ const fileSet = new Set(files);
368
+ for (const edge of this.edges) {
369
+ const sourceInCluster = fileSet.has(edge.source);
370
+ const targetInCluster = fileSet.has(edge.target);
371
+ if (sourceInCluster && targetInCluster) {
372
+ internalEdges++;
373
+ }
374
+ else if (sourceInCluster || targetInCluster) {
375
+ externalEdges++;
376
+ }
377
+ }
378
+ // Calculate cohesion (internal density)
379
+ const possibleInternalEdges = files.length * (files.length - 1);
380
+ const cohesion = possibleInternalEdges > 0 ? internalEdges / possibleInternalEdges : 0;
381
+ // Calculate coupling (external connections)
382
+ const totalEdges = internalEdges + externalEdges;
383
+ const coupling = totalEdges > 0 ? externalEdges / totalEdges : 0;
384
+ // Generate suggested domain name
385
+ const suggestedDomain = this.suggestDomainName(dir, files);
386
+ clusters.push({
387
+ id: `cluster-${clusterId}`,
388
+ name: dir,
389
+ files,
390
+ internalEdges,
391
+ externalEdges,
392
+ cohesion,
393
+ coupling,
394
+ suggestedDomain,
395
+ color: CLUSTER_PALETTE[clusterId++ % CLUSTER_PALETTE.length],
396
+ isStructural: internalEdges > 0,
397
+ });
398
+ }
399
+ return clusters;
400
+ }
401
+ /**
402
+ * Suggest a domain name based on directory and file contents
403
+ */
404
+ suggestDomainName(dir, files) {
405
+ // Extract meaningful name from directory
406
+ const parts = dir.split('/').filter(p => p && p !== '(root)');
407
+ // Common patterns to convert
408
+ const patterns = [
409
+ [/^src$/i, ''],
410
+ [/^lib$/i, ''],
411
+ [/^app$/i, ''],
412
+ [/^(api|routes|endpoints?)$/i, 'api'],
413
+ [/^(models?|entities|schemas?)$/i, 'domain'],
414
+ [/^(services?)$/i, 'services'],
415
+ [/^(controllers?)$/i, 'controllers'],
416
+ [/^(utils?|helpers?|common)$/i, 'utilities'],
417
+ [/^(components?)$/i, 'components'],
418
+ [/^(hooks?)$/i, 'hooks'],
419
+ [/^(auth|authentication)$/i, 'authentication'],
420
+ [/^(users?)$/i, 'users'],
421
+ [/^(products?)$/i, 'products'],
422
+ [/^(orders?)$/i, 'orders'],
423
+ [/^(payments?)$/i, 'payments'],
424
+ [/^(core)$/i, 'core'],
425
+ ];
426
+ // Try to find a meaningful name
427
+ for (const part of parts.reverse()) {
428
+ for (const [pattern, replacement] of patterns) {
429
+ if (pattern.test(part)) {
430
+ return replacement || part.toLowerCase();
431
+ }
432
+ }
433
+ // If no pattern matches, use the part as-is
434
+ if (!/^(src|lib|app)$/i.test(part)) {
435
+ return part.toLowerCase().replace(/[^a-z0-9]/g, '-');
436
+ }
437
+ }
438
+ // Fallback: use first file's name pattern
439
+ if (files.length > 0) {
440
+ const firstFile = this.nodes.get(files[0])?.file.name ?? 'unknown';
441
+ return firstFile.replace(/\.(ts|js|tsx|jsx|py)x?$/, '').toLowerCase();
442
+ }
443
+ return 'misc';
444
+ }
445
+ /**
446
+ * Detect cycles in the dependency graph using DFS
447
+ */
448
+ detectCycles() {
449
+ const cycles = [];
450
+ const visited = new Set();
451
+ const recursionStack = new Set();
452
+ const path = [];
453
+ const dfs = (node) => {
454
+ visited.add(node);
455
+ recursionStack.add(node);
456
+ path.push(node);
457
+ const neighbors = this.adjacencyList.get(node) ?? new Set();
458
+ for (const neighbor of neighbors) {
459
+ if (!visited.has(neighbor)) {
460
+ dfs(neighbor);
461
+ }
462
+ else if (recursionStack.has(neighbor)) {
463
+ // Found a cycle
464
+ const cycleStart = path.indexOf(neighbor);
465
+ const cycle = path.slice(cycleStart);
466
+ cycle.push(neighbor); // Complete the cycle
467
+ // Check if this cycle is not a duplicate (or rotation of existing)
468
+ if (!this.isDuplicateCycle(cycles, cycle)) {
469
+ cycles.push(cycle);
470
+ }
471
+ }
472
+ }
473
+ path.pop();
474
+ recursionStack.delete(node);
475
+ };
476
+ for (const nodeId of this.nodes.keys()) {
477
+ if (!visited.has(nodeId)) {
478
+ dfs(nodeId);
479
+ }
480
+ }
481
+ return cycles;
482
+ }
483
+ /**
484
+ * Check if a cycle is a duplicate or rotation of an existing cycle
485
+ */
486
+ isDuplicateCycle(existingCycles, newCycle) {
487
+ const normalizedNew = this.normalizeCycle(newCycle);
488
+ for (const existing of existingCycles) {
489
+ const normalizedExisting = this.normalizeCycle(existing);
490
+ if (normalizedNew === normalizedExisting) {
491
+ return true;
492
+ }
493
+ }
494
+ return false;
495
+ }
496
+ /**
497
+ * Normalize a cycle for comparison (smallest element first, then compare)
498
+ */
499
+ normalizeCycle(cycle) {
500
+ // Remove the duplicate closing element
501
+ const clean = cycle.slice(0, -1);
502
+ if (clean.length === 0)
503
+ return '';
504
+ // Find the smallest element
505
+ const minIdx = clean.indexOf(clean.reduce((min, curr) => (curr < min ? curr : min)));
506
+ // Rotate so smallest is first
507
+ const rotated = [...clean.slice(minIdx), ...clean.slice(0, minIdx)];
508
+ return rotated.join('|');
509
+ }
510
+ /**
511
+ * Generate various rankings of nodes
512
+ */
513
+ generateRankings(clusters) {
514
+ const nodes = Array.from(this.nodes.values());
515
+ // By PageRank importance — use .slice() to avoid mutating the shared array
516
+ const byImportance = nodes
517
+ .slice()
518
+ .sort((a, b) => b.metrics.pageRank - a.metrics.pageRank)
519
+ .map(n => n.id);
520
+ // By total connectivity (in + out degree)
521
+ const byConnectivity = nodes
522
+ .slice()
523
+ .sort((a, b) => (b.metrics.inDegree + b.metrics.outDegree) -
524
+ (a.metrics.inDegree + a.metrics.outDegree))
525
+ .map(n => n.id);
526
+ // Cluster centers (highest in-degree within each cluster)
527
+ const clusterCenters = [];
528
+ for (const cluster of clusters) {
529
+ const clusterNodes = cluster.files
530
+ .map(f => this.nodes.get(f))
531
+ .filter((n) => n !== undefined);
532
+ if (clusterNodes.length > 0) {
533
+ const center = clusterNodes.reduce((max, n) => n.metrics.inDegree > max.metrics.inDegree ? n : max);
534
+ clusterCenters.push(center.id);
535
+ }
536
+ }
537
+ // Leaf nodes (high out-degree, low in-degree)
538
+ const leafNodes = nodes
539
+ .filter(n => n.metrics.outDegree > 0 && n.metrics.inDegree === 0)
540
+ .sort((a, b) => b.metrics.outDegree - a.metrics.outDegree)
541
+ .map(n => n.id);
542
+ // Bridge nodes (high betweenness)
543
+ const bridgeNodes = nodes
544
+ .filter(n => n.metrics.betweenness > 0.1)
545
+ .sort((a, b) => b.metrics.betweenness - a.metrics.betweenness)
546
+ .map(n => n.id);
547
+ // Orphan nodes (no connections)
548
+ const orphanNodes = nodes
549
+ .filter(n => n.metrics.inDegree === 0 && n.metrics.outDegree === 0)
550
+ .map(n => n.id);
551
+ return {
552
+ byImportance,
553
+ byConnectivity,
554
+ clusterCenters,
555
+ leafNodes,
556
+ bridgeNodes,
557
+ orphanNodes,
558
+ };
559
+ }
560
+ /**
561
+ * Calculate overall statistics
562
+ */
563
+ calculateStatistics(clusters, cycles) {
564
+ const nodeCount = this.nodes.size;
565
+ const edgeCount = this.edges.length;
566
+ // Average degree
567
+ let totalDegree = 0;
568
+ for (const node of this.nodes.values()) {
569
+ totalDegree += node.metrics.inDegree + node.metrics.outDegree;
570
+ }
571
+ const avgDegree = nodeCount > 0 ? totalDegree / nodeCount : 0;
572
+ // Density: actual edges / possible edges
573
+ const possibleEdges = nodeCount * (nodeCount - 1);
574
+ const density = possibleEdges > 0 ? edgeCount / possibleEdges : 0;
575
+ return {
576
+ nodeCount,
577
+ edgeCount,
578
+ importEdgeCount: edgeCount - this.httpEdgeCount,
579
+ httpEdgeCount: this.httpEdgeCount,
580
+ avgDegree,
581
+ density,
582
+ clusterCount: clusters.length,
583
+ structuralClusterCount: clusters.filter(c => c.isStructural).length,
584
+ cycleCount: cycles.length,
585
+ };
586
+ }
587
+ }
588
+ // ============================================================================
589
+ // CONVENIENCE FUNCTIONS
590
+ // ============================================================================
591
+ /**
592
+ * Build a dependency graph from scored files
593
+ */
594
+ export async function buildDependencyGraph(files, options) {
595
+ const builder = new DependencyGraphBuilder(options);
596
+ return builder.build(files);
597
+ }
598
+ // ============================================================================
599
+ // CALL-GRAPH EDGE INJECTION
600
+ // ============================================================================
601
+ /**
602
+ * Languages that share a module-level namespace without explicit intra-file imports.
603
+ * For these, dependency edges must be derived from the call graph rather than imports.
604
+ */
605
+ const IMPLICIT_IMPORT_LANGS = new Set(['Swift', 'C++', 'C']);
606
+ /**
607
+ * Synthesize dependency edges from cross-file call edges and inject them into
608
+ * an existing DependencyGraphResult in-place.
609
+ *
610
+ * Use this for languages like Swift or C++ that don't have explicit intra-module
611
+ * imports, resulting in an empty dep graph when only import-based edges are built.
612
+ */
613
+ export function injectCallGraphEdges(depGraph, callEdges, nodeFilePath) {
614
+ // Build a Set of node IDs for quick membership test
615
+ const nodeIds = new Set(depGraph.nodes.map(n => n.id));
616
+ // Collect unique file-level edges
617
+ const seen = new Set();
618
+ const newEdges = [];
619
+ for (const ce of callEdges) {
620
+ const callerFile = nodeFilePath(ce.callerId);
621
+ const calleeFile = nodeFilePath(ce.calleeId);
622
+ if (!callerFile || !calleeFile || callerFile === calleeFile)
623
+ continue;
624
+ if (!nodeIds.has(callerFile) || !nodeIds.has(calleeFile))
625
+ continue;
626
+ const key = `${callerFile}→${calleeFile}`;
627
+ if (seen.has(key))
628
+ continue;
629
+ seen.add(key);
630
+ newEdges.push({ source: callerFile, target: calleeFile, importedNames: [], isTypeOnly: false, weight: 1, isCallEdge: true });
631
+ }
632
+ if (newEdges.length === 0)
633
+ return;
634
+ depGraph.edges.push(...newEdges);
635
+ // Recompute node in/out degrees
636
+ const inDeg = new Map();
637
+ const outDeg = new Map();
638
+ for (const e of depGraph.edges) {
639
+ outDeg.set(e.source, (outDeg.get(e.source) ?? 0) + 1);
640
+ inDeg.set(e.target, (inDeg.get(e.target) ?? 0) + 1);
641
+ }
642
+ for (const node of depGraph.nodes) {
643
+ node.metrics.inDegree = inDeg.get(node.id) ?? 0;
644
+ node.metrics.outDegree = outDeg.get(node.id) ?? 0;
645
+ }
646
+ // Update statistics
647
+ depGraph.statistics.edgeCount = depGraph.edges.length;
648
+ const totalDegree = depGraph.nodes.reduce((s, n) => s + n.metrics.inDegree + n.metrics.outDegree, 0);
649
+ depGraph.statistics.avgDegree = depGraph.nodes.length > 0 ? totalDegree / depGraph.nodes.length : 0;
650
+ const possible = depGraph.statistics.nodeCount * (depGraph.statistics.nodeCount - 1);
651
+ depGraph.statistics.density = possible > 0 ? depGraph.statistics.edgeCount / possible : 0;
652
+ // Recompute cluster internalEdges and rebuild structuralClusters.
653
+ // Without this, the viewer's cluster view stays empty even when edges exist.
654
+ const fileToCluster = new Map();
655
+ for (const cl of depGraph.clusters) {
656
+ for (const fid of cl.files)
657
+ fileToCluster.set(fid, cl.id);
658
+ }
659
+ const clusterInternalEdges = new Map();
660
+ for (const e of depGraph.edges) {
661
+ const sc = fileToCluster.get(e.source);
662
+ const tc = fileToCluster.get(e.target);
663
+ if (sc && sc === tc)
664
+ clusterInternalEdges.set(sc, (clusterInternalEdges.get(sc) ?? 0) + 1);
665
+ }
666
+ for (const cl of depGraph.clusters) {
667
+ cl.internalEdges = clusterInternalEdges.get(cl.id) ?? 0;
668
+ cl.isStructural = cl.internalEdges > 0;
669
+ }
670
+ depGraph.structuralClusters = depGraph.clusters.filter(cl => cl.internalEdges > 0);
671
+ depGraph.statistics.structuralClusterCount = depGraph.structuralClusters.length;
672
+ }
673
+ export { IMPLICIT_IMPORT_LANGS };
674
+ // ============================================================================
675
+ // EXPORT FORMATS
676
+ // ============================================================================
677
+ /**
678
+ * Convert graph to D3.js force graph format
679
+ */
680
+ export function toD3Format(result) {
681
+ // Use only structural clusters for group colouring — directory-only
682
+ // clusters (cohesion=0) would produce too many indistinct colour groups.
683
+ const clusterIndex = new Map();
684
+ result.structuralClusters.forEach((cluster, idx) => {
685
+ for (const file of cluster.files) {
686
+ clusterIndex.set(file, idx);
687
+ }
688
+ });
689
+ return {
690
+ nodes: result.nodes.map(n => ({
691
+ id: n.file.path,
692
+ group: clusterIndex.get(n.id) ?? -1,
693
+ score: n.metrics.pageRank,
694
+ })),
695
+ links: result.edges.map(e => ({
696
+ source: result.nodes.find(n => n.id === e.source)?.file.path ?? e.source,
697
+ target: result.nodes.find(n => n.id === e.target)?.file.path ?? e.target,
698
+ value: e.weight,
699
+ })),
700
+ };
701
+ }
702
+ /**
703
+ * Convert graph to Mermaid diagram syntax
704
+ */
705
+ export function toMermaidFormat(result, maxNodes = 50) {
706
+ const lines = ['graph TD'];
707
+ // Take top nodes by importance
708
+ const topNodes = result.rankings.byImportance.slice(0, maxNodes);
709
+ const nodeSet = new Set(topNodes);
710
+ // Create node labels
711
+ const nodeLabels = new Map();
712
+ result.nodes
713
+ .filter(n => nodeSet.has(n.id))
714
+ .forEach((n, idx) => {
715
+ const label = `N${idx}`;
716
+ nodeLabels.set(n.id, label);
717
+ const name = n.file.name.replace(/["[\]]/g, '');
718
+ lines.push(` ${label}["${name}"]`);
719
+ });
720
+ // Create edges
721
+ for (const edge of result.edges) {
722
+ const sourceLabel = nodeLabels.get(edge.source);
723
+ const targetLabel = nodeLabels.get(edge.target);
724
+ if (sourceLabel && targetLabel) {
725
+ const style = edge.isTypeOnly ? '-.->' : '-->';
726
+ lines.push(` ${sourceLabel} ${style} ${targetLabel}`);
727
+ }
728
+ }
729
+ return lines.join('\n');
730
+ }
731
+ /**
732
+ * Convert graph to DOT format (Graphviz)
733
+ */
734
+ export function toDotFormat(result) {
735
+ const lines = ['digraph Dependencies {'];
736
+ lines.push(' rankdir=LR;');
737
+ lines.push(' node [shape=box];');
738
+ // Create node definitions with labels
739
+ for (const node of result.nodes) {
740
+ const name = node.file.name.replace(/"/g, '\\"');
741
+ const color = node.metrics.pageRank > 0.5 ? 'lightblue' : 'white';
742
+ lines.push(` "${node.id}" [label="${name}" fillcolor="${color}" style="filled"];`);
743
+ }
744
+ // Create edges
745
+ for (const edge of result.edges) {
746
+ const style = edge.isTypeOnly ? 'dashed' : 'solid';
747
+ lines.push(` "${edge.source}" -> "${edge.target}" [style="${style}"];`);
748
+ }
749
+ lines.push('}');
750
+ return lines.join('\n');
751
+ }
752
+ //# sourceMappingURL=dependency-graph.js.map