codebase-onboarder 0.5.0 → 0.7.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 (448) hide show
  1. package/README.md +196 -47
  2. package/bin/build-if-source.js +23 -0
  3. package/cli/commands.d.ts +26 -0
  4. package/cli/commands.js +836 -811
  5. package/cli/commands.js.map +1 -0
  6. package/cli/explorer/advanced.d.ts +14 -0
  7. package/cli/explorer/advanced.js +449 -0
  8. package/cli/explorer/advanced.js.map +1 -0
  9. package/cli/explorer/app.d.ts +1 -0
  10. package/cli/explorer/app.js +396 -229
  11. package/cli/explorer/app.js.map +1 -0
  12. package/cli/explorer/assistant.d.ts +9 -0
  13. package/cli/explorer/assistant.js +58 -0
  14. package/cli/explorer/assistant.js.map +1 -0
  15. package/cli/explorer/commands.d.ts +17 -0
  16. package/cli/explorer/commands.js +400 -162
  17. package/cli/explorer/commands.js.map +1 -0
  18. package/cli/explorer/featureViews.d.ts +124 -0
  19. package/cli/explorer/featureViews.js +179 -0
  20. package/cli/explorer/featureViews.js.map +1 -0
  21. package/cli/explorer/github.d.ts +21 -0
  22. package/cli/explorer/github.js +73 -0
  23. package/cli/explorer/github.js.map +1 -0
  24. package/cli/explorer/graphs.d.ts +7 -0
  25. package/cli/explorer/graphs.js +173 -0
  26. package/cli/explorer/graphs.js.map +1 -0
  27. package/cli/explorer/picker.d.ts +22 -0
  28. package/cli/explorer/picker.js +150 -0
  29. package/cli/explorer/picker.js.map +1 -0
  30. package/cli/explorer/report.d.ts +85 -0
  31. package/cli/explorer/report.js +60 -0
  32. package/cli/explorer/report.js.map +1 -0
  33. package/cli/explorer/session.d.ts +449 -0
  34. package/cli/explorer/session.js +184 -95
  35. package/cli/explorer/session.js.map +1 -0
  36. package/cli/explorer/views.d.ts +19 -0
  37. package/cli/explorer/views.js +496 -412
  38. package/cli/explorer/views.js.map +1 -0
  39. package/cli/explorer/wrap.d.ts +1 -0
  40. package/cli/explorer/wrap.js +33 -0
  41. package/cli/explorer/wrap.js.map +1 -0
  42. package/cli/main.d.ts +1 -0
  43. package/cli/main.js +235 -138
  44. package/cli/main.js.map +1 -0
  45. package/cli/prompt.d.ts +5 -0
  46. package/cli/prompt.js +84 -80
  47. package/cli/prompt.js.map +1 -0
  48. package/cli/scanOptions.d.ts +2 -0
  49. package/cli/scanOptions.js +11 -0
  50. package/cli/scanOptions.js.map +1 -0
  51. package/cli/ui.d.ts +33 -0
  52. package/cli/ui.js +55 -35
  53. package/cli/ui.js.map +1 -0
  54. package/cli/wizard.d.ts +187 -0
  55. package/cli/wizard.js +304 -284
  56. package/cli/wizard.js.map +1 -0
  57. package/package.json +15 -4
  58. package/public/app.d.ts +1 -0
  59. package/public/app.js +1057 -1009
  60. package/public/app.js.map +1 -0
  61. package/public/browser.d.ts +68 -0
  62. package/public/browser.js +2 -0
  63. package/public/browser.js.map +1 -0
  64. package/public/index.html +30 -13
  65. package/public/js/about.d.ts +6 -0
  66. package/public/js/about.js +165 -172
  67. package/public/js/about.js.map +1 -0
  68. package/public/js/aiDraft.d.ts +3 -0
  69. package/public/js/aiDraft.js +116 -124
  70. package/public/js/aiDraft.js.map +1 -0
  71. package/public/js/analysisPanel.d.ts +7 -0
  72. package/public/js/analysisPanel.js +166 -166
  73. package/public/js/analysisPanel.js.map +1 -0
  74. package/public/js/analysisReport.d.ts +38 -0
  75. package/public/js/analysisReport.js +105 -110
  76. package/public/js/analysisReport.js.map +1 -0
  77. package/public/js/api.d.ts +26 -0
  78. package/public/js/api.js +176 -167
  79. package/public/js/api.js.map +1 -0
  80. package/public/js/atlas.d.ts +6 -0
  81. package/public/js/atlas.js +50 -58
  82. package/public/js/atlas.js.map +1 -0
  83. package/public/js/blameView.d.ts +2 -0
  84. package/public/js/blameView.js +36 -37
  85. package/public/js/blameView.js.map +1 -0
  86. package/public/js/codeTab.d.ts +3 -0
  87. package/public/js/codeTab.js +175 -180
  88. package/public/js/codeTab.js.map +1 -0
  89. package/public/js/codeViewer.d.ts +5 -0
  90. package/public/js/codeViewer.js +162 -150
  91. package/public/js/codeViewer.js.map +1 -0
  92. package/public/js/components/FileChip.d.ts +9 -0
  93. package/public/js/components/FileChip.js +45 -49
  94. package/public/js/components/FileChip.js.map +1 -0
  95. package/public/js/components/MetricSparkline.d.ts +7 -0
  96. package/public/js/components/MetricSparkline.js +35 -44
  97. package/public/js/components/MetricSparkline.js.map +1 -0
  98. package/public/js/components/RiskBadge.d.ts +9 -0
  99. package/public/js/components/RiskBadge.js +55 -63
  100. package/public/js/components/RiskBadge.js.map +1 -0
  101. package/public/js/deepAnalysisView.d.ts +99 -0
  102. package/public/js/deepAnalysisView.js +282 -302
  103. package/public/js/deepAnalysisView.js.map +1 -0
  104. package/public/js/diagramPane.d.ts +8 -0
  105. package/public/js/diagramPane.js +133 -135
  106. package/public/js/diagramPane.js.map +1 -0
  107. package/public/js/diffView.d.ts +6 -0
  108. package/public/js/diffView.js +222 -209
  109. package/public/js/diffView.js.map +1 -0
  110. package/public/js/docsView.d.ts +2 -0
  111. package/public/js/docsView.js +441 -442
  112. package/public/js/docsView.js.map +1 -0
  113. package/public/js/dom.d.ts +189 -0
  114. package/public/js/dom.js +5 -0
  115. package/public/js/dom.js.map +1 -0
  116. package/public/js/fileSourceBrowser.d.ts +5 -0
  117. package/public/js/fileSourceBrowser.js +33 -41
  118. package/public/js/fileSourceBrowser.js.map +1 -0
  119. package/public/js/flameGraph.d.ts +5 -0
  120. package/public/js/flameGraph.js +62 -72
  121. package/public/js/flameGraph.js.map +1 -0
  122. package/public/js/forceGraph.d.ts +10 -0
  123. package/public/js/forceGraph.js +581 -556
  124. package/public/js/forceGraph.js.map +1 -0
  125. package/public/js/heatmap.d.ts +4 -0
  126. package/public/js/heatmap.js +142 -164
  127. package/public/js/heatmap.js.map +1 -0
  128. package/public/js/highlight.d.ts +2 -0
  129. package/public/js/highlight.js +116 -107
  130. package/public/js/highlight.js.map +1 -0
  131. package/public/js/html.d.ts +2 -0
  132. package/public/js/html.js +14 -44
  133. package/public/js/html.js.map +1 -0
  134. package/public/js/insightsView.d.ts +5 -0
  135. package/public/js/insightsView.js +93 -111
  136. package/public/js/insightsView.js.map +1 -0
  137. package/public/js/inspector.d.ts +37 -0
  138. package/public/js/inspector.js +416 -445
  139. package/public/js/inspector.js.map +1 -0
  140. package/public/js/llm.d.ts +113 -0
  141. package/public/js/llm.js +233 -272
  142. package/public/js/llm.js.map +1 -0
  143. package/public/js/mapView.d.ts +3 -0
  144. package/public/js/mapView.js +121 -120
  145. package/public/js/mapView.js.map +1 -0
  146. package/public/js/markdown.d.ts +3 -0
  147. package/public/js/markdown.js +84 -91
  148. package/public/js/markdown.js.map +1 -0
  149. package/public/js/mindmap.d.ts +32 -0
  150. package/public/js/mindmap.js +244 -259
  151. package/public/js/mindmap.js.map +1 -0
  152. package/public/js/mobilePanels.d.ts +5 -0
  153. package/public/js/mobilePanels.js +50 -0
  154. package/public/js/mobilePanels.js.map +1 -0
  155. package/public/js/repoFiles.d.ts +12 -0
  156. package/public/js/repoFiles.js +28 -27
  157. package/public/js/repoFiles.js.map +1 -0
  158. package/public/js/reviewView.d.ts +28 -0
  159. package/public/js/reviewView.js +256 -0
  160. package/public/js/reviewView.js.map +1 -0
  161. package/public/js/sbomView.d.ts +3 -0
  162. package/public/js/sbomView.js +59 -67
  163. package/public/js/sbomView.js.map +1 -0
  164. package/public/js/scanCache.d.ts +16 -0
  165. package/public/js/scanCache.js +67 -65
  166. package/public/js/scanCache.js.map +1 -0
  167. package/public/js/search.d.ts +7 -0
  168. package/public/js/search.js +868 -800
  169. package/public/js/search.js.map +1 -0
  170. package/public/js/searchLocal.d.ts +42 -0
  171. package/public/js/searchLocal.js +87 -0
  172. package/public/js/searchLocal.js.map +1 -0
  173. package/public/js/serverSettings.d.ts +5 -0
  174. package/public/js/serverSettings.js +153 -164
  175. package/public/js/serverSettings.js.map +1 -0
  176. package/public/js/state.d.ts +798 -0
  177. package/public/js/state.js +114 -122
  178. package/public/js/state.js.map +1 -0
  179. package/public/js/tour.d.ts +6 -0
  180. package/public/js/tour.js +5 -7
  181. package/public/js/tour.js.map +1 -0
  182. package/public/js/transitions.d.ts +2 -0
  183. package/public/js/transitions.js +9 -10
  184. package/public/js/transitions.js.map +1 -0
  185. package/public/js/tree.d.ts +12 -0
  186. package/public/js/tree.js +157 -154
  187. package/public/js/tree.js.map +1 -0
  188. package/public/js/workflowsView.d.ts +3 -0
  189. package/public/js/workflowsView.js +15 -22
  190. package/public/js/workflowsView.js.map +1 -0
  191. package/public/search.css +495 -0
  192. package/public/styles.css +163 -346
  193. package/public/workbench.css +166 -0
  194. package/server/apiAuth.d.ts +3 -0
  195. package/server/apiAuth.js +18 -20
  196. package/server/apiAuth.js.map +1 -0
  197. package/server/apiDiff.d.ts +2 -0
  198. package/server/apiDiff.js +20 -18
  199. package/server/apiDiff.js.map +1 -0
  200. package/server/apiDocs.d.ts +2 -0
  201. package/server/apiDocs.js +38 -40
  202. package/server/apiDocs.js.map +1 -0
  203. package/server/apiFile.d.ts +1 -0
  204. package/server/apiFile.js +14 -17
  205. package/server/apiFile.js.map +1 -0
  206. package/server/apiGitBlame.d.ts +2 -0
  207. package/server/apiGitBlame.js +50 -51
  208. package/server/apiGitBlame.js.map +1 -0
  209. package/server/apiMcp.d.ts +4 -0
  210. package/server/apiMcp.js +64 -66
  211. package/server/apiMcp.js.map +1 -0
  212. package/server/apiReview.d.ts +2 -0
  213. package/server/apiReview.js +45 -0
  214. package/server/apiReview.js.map +1 -0
  215. package/server/apiScan.d.ts +5 -0
  216. package/server/apiScan.js +90 -71
  217. package/server/apiScan.js.map +1 -0
  218. package/server/apiSearch.d.ts +33 -0
  219. package/server/apiSearch.js +184 -200
  220. package/server/apiSearch.js.map +1 -0
  221. package/server/apiSettings.d.ts +4 -0
  222. package/server/apiSettings.js +84 -85
  223. package/server/apiSettings.js.map +1 -0
  224. package/server/apiTools.d.ts +3 -0
  225. package/server/apiTools.js +55 -56
  226. package/server/apiTools.js.map +1 -0
  227. package/server/auth.d.ts +5 -0
  228. package/server/auth.js +54 -51
  229. package/server/auth.js.map +1 -0
  230. package/server/config.d.ts +42 -0
  231. package/server/config.js +189 -194
  232. package/server/config.js.map +1 -0
  233. package/server/daemon.d.ts +12 -0
  234. package/server/daemon.js +124 -114
  235. package/server/daemon.js.map +1 -0
  236. package/server/fileSourceNode.d.ts +2 -0
  237. package/server/fileSourceNode.js +34 -36
  238. package/server/fileSourceNode.js.map +1 -0
  239. package/server/gitClone.d.ts +9 -0
  240. package/server/gitClone.js +59 -61
  241. package/server/gitClone.js.map +1 -0
  242. package/server/gitDiff.d.ts +36 -0
  243. package/server/gitDiff.js +271 -169
  244. package/server/gitDiff.js.map +1 -0
  245. package/server/gitHistory.d.ts +12 -0
  246. package/server/gitHistory.js +80 -80
  247. package/server/gitHistory.js.map +1 -0
  248. package/server/gitRemote.d.ts +12 -0
  249. package/server/gitRemote.js +60 -0
  250. package/server/gitRemote.js.map +1 -0
  251. package/server/htmlText.d.ts +4 -0
  252. package/server/htmlText.js +16 -23
  253. package/server/htmlText.js.map +1 -0
  254. package/server/http.d.ts +5 -0
  255. package/server/http.js +27 -30
  256. package/server/http.js.map +1 -0
  257. package/server/httpGuards.d.ts +2 -0
  258. package/server/httpGuards.js +47 -43
  259. package/server/httpGuards.js.map +1 -0
  260. package/server/https.d.ts +34 -0
  261. package/server/https.js +121 -111
  262. package/server/https.js.map +1 -0
  263. package/server/index.d.ts +40 -0
  264. package/server/index.js +139 -147
  265. package/server/index.js.map +1 -0
  266. package/server/layout.d.ts +26 -0
  267. package/server/layout.js +59 -37
  268. package/server/layout.js.map +1 -0
  269. package/server/llmProxy.d.ts +3 -0
  270. package/server/llmProxy.js +137 -135
  271. package/server/llmProxy.js.map +1 -0
  272. package/server/logger.d.ts +38 -0
  273. package/server/logger.js +198 -211
  274. package/server/logger.js.map +1 -0
  275. package/server/mcp/analysis.d.ts +29 -0
  276. package/server/mcp/analysis.js +99 -120
  277. package/server/mcp/analysis.js.map +1 -0
  278. package/server/mcp/http.d.ts +9 -0
  279. package/server/mcp/http.js +128 -137
  280. package/server/mcp/http.js.map +1 -0
  281. package/server/mcp/runner.d.ts +68 -0
  282. package/server/mcp/runner.js +208 -218
  283. package/server/mcp/runner.js.map +1 -0
  284. package/server/mcp/server.d.ts +29 -0
  285. package/server/mcp/server.js +166 -179
  286. package/server/mcp/server.js.map +1 -0
  287. package/server/mcp/standalone.d.ts +1 -0
  288. package/server/mcp/standalone.js +8 -10
  289. package/server/mcp/standalone.js.map +1 -0
  290. package/server/mcp/tools.d.ts +2020 -0
  291. package/server/mcp/tools.js +523 -574
  292. package/server/mcp/tools.js.map +1 -0
  293. package/server/paths.d.ts +3 -0
  294. package/server/paths.js +17 -15
  295. package/server/paths.js.map +1 -0
  296. package/server/pidfile.d.ts +9 -0
  297. package/server/pidfile.js +43 -45
  298. package/server/pidfile.js.map +1 -0
  299. package/server/review.d.ts +5 -0
  300. package/server/review.js +35 -0
  301. package/server/review.js.map +1 -0
  302. package/server/router.d.ts +33 -0
  303. package/server/router.js +191 -197
  304. package/server/router.js.map +1 -0
  305. package/server/scanRequest.d.ts +3 -0
  306. package/server/scanRequest.js +36 -0
  307. package/server/scanRequest.js.map +1 -0
  308. package/server/searchIndex.d.ts +17 -0
  309. package/server/searchIndex.js +83 -80
  310. package/server/searchIndex.js.map +1 -0
  311. package/server/sessions.d.ts +14 -0
  312. package/server/sessions.js +62 -70
  313. package/server/sessions.js.map +1 -0
  314. package/server/startup.d.ts +118 -0
  315. package/server/startup.js +143 -148
  316. package/server/startup.js.map +1 -0
  317. package/server/static.d.ts +6 -0
  318. package/server/static.js +28 -31
  319. package/server/static.js.map +1 -0
  320. package/server/tools/install.d.ts +4 -0
  321. package/server/tools/install.js +176 -185
  322. package/server/tools/install.js.map +1 -0
  323. package/server/tools/parse.d.ts +8 -0
  324. package/server/tools/parse.js +112 -114
  325. package/server/tools/parse.js.map +1 -0
  326. package/server/tools/platform.d.ts +9 -0
  327. package/server/tools/platform.js +49 -47
  328. package/server/tools/platform.js.map +1 -0
  329. package/server/tools/registry.d.ts +137 -0
  330. package/server/tools/registry.js +173 -172
  331. package/server/tools/registry.js.map +1 -0
  332. package/server/tools/scan.d.ts +34 -0
  333. package/server/tools/scan.js +89 -98
  334. package/server/tools/scan.js.map +1 -0
  335. package/server/tools.d.ts +34 -0
  336. package/server/tools.js +94 -107
  337. package/server/tools.js.map +1 -0
  338. package/server/tunnel.d.ts +29 -0
  339. package/server/tunnel.js +61 -66
  340. package/server/tunnel.js.map +1 -0
  341. package/shared/analyzer/docs.d.ts +16 -0
  342. package/shared/analyzer/docs.js +99 -93
  343. package/shared/analyzer/docs.js.map +1 -0
  344. package/shared/analyzer/explainLocal.d.ts +4 -0
  345. package/shared/analyzer/explainLocal.js +122 -142
  346. package/shared/analyzer/explainLocal.js.map +1 -0
  347. package/shared/analyzer/github.d.ts +37 -0
  348. package/shared/analyzer/github.js +79 -0
  349. package/shared/analyzer/github.js.map +1 -0
  350. package/shared/analyzer/graph.d.ts +41 -0
  351. package/shared/analyzer/graph.js +393 -400
  352. package/shared/analyzer/graph.js.map +1 -0
  353. package/shared/analyzer/health.d.ts +33 -0
  354. package/shared/analyzer/health.js +197 -193
  355. package/shared/analyzer/health.js.map +1 -0
  356. package/shared/analyzer/history.d.ts +29 -0
  357. package/shared/analyzer/history.js +110 -111
  358. package/shared/analyzer/history.js.map +1 -0
  359. package/shared/analyzer/jsonConfig.d.ts +2 -0
  360. package/shared/analyzer/jsonConfig.js +61 -0
  361. package/shared/analyzer/jsonConfig.js.map +1 -0
  362. package/shared/analyzer/languages/csharp.d.ts +26 -0
  363. package/shared/analyzer/languages/csharp.js +83 -88
  364. package/shared/analyzer/languages/csharp.js.map +1 -0
  365. package/shared/analyzer/languages/generic.d.ts +23 -0
  366. package/shared/analyzer/languages/generic.js +94 -105
  367. package/shared/analyzer/languages/generic.js.map +1 -0
  368. package/shared/analyzer/languages/go.d.ts +24 -0
  369. package/shared/analyzer/languages/go.js +45 -54
  370. package/shared/analyzer/languages/go.js.map +1 -0
  371. package/shared/analyzer/languages/index.d.ts +6 -0
  372. package/shared/analyzer/languages/index.js +19 -20
  373. package/shared/analyzer/languages/index.js.map +1 -0
  374. package/shared/analyzer/languages/java.d.ts +20 -0
  375. package/shared/analyzer/languages/java.js +73 -78
  376. package/shared/analyzer/languages/java.js.map +1 -0
  377. package/shared/analyzer/languages/javascript.d.ts +12 -0
  378. package/shared/analyzer/languages/javascript.js +258 -209
  379. package/shared/analyzer/languages/javascript.js.map +1 -0
  380. package/shared/analyzer/languages/python.d.ts +23 -0
  381. package/shared/analyzer/languages/python.js +92 -100
  382. package/shared/analyzer/languages/python.js.map +1 -0
  383. package/shared/analyzer/languages/rust.d.ts +17 -0
  384. package/shared/analyzer/languages/rust.js +96 -98
  385. package/shared/analyzer/languages/rust.js.map +1 -0
  386. package/shared/analyzer/languages/typescript.d.ts +11 -0
  387. package/shared/analyzer/languages/typescript.js +117 -116
  388. package/shared/analyzer/languages/typescript.js.map +1 -0
  389. package/shared/analyzer/licenses.d.ts +18 -0
  390. package/shared/analyzer/licenses.js +130 -133
  391. package/shared/analyzer/licenses.js.map +1 -0
  392. package/shared/analyzer/metrics.d.ts +20 -0
  393. package/shared/analyzer/metrics.js +112 -104
  394. package/shared/analyzer/metrics.js.map +1 -0
  395. package/shared/analyzer/pathUtil.d.ts +10 -0
  396. package/shared/analyzer/pathUtil.js +29 -35
  397. package/shared/analyzer/pathUtil.js.map +1 -0
  398. package/shared/analyzer/patterns.d.ts +11 -0
  399. package/shared/analyzer/patterns.js +231 -253
  400. package/shared/analyzer/patterns.js.map +1 -0
  401. package/shared/analyzer/scan.d.ts +62 -0
  402. package/shared/analyzer/scan.js +451 -442
  403. package/shared/analyzer/scan.js.map +1 -0
  404. package/shared/analyzer/scanControl.d.ts +11 -0
  405. package/shared/analyzer/scanControl.js +62 -0
  406. package/shared/analyzer/scanControl.js.map +1 -0
  407. package/shared/analyzer/security.d.ts +18 -0
  408. package/shared/analyzer/security.js +159 -159
  409. package/shared/analyzer/security.js.map +1 -0
  410. package/shared/analyzer/services.d.ts +5 -0
  411. package/shared/analyzer/services.js +141 -138
  412. package/shared/analyzer/services.js.map +1 -0
  413. package/shared/analyzer/stack.d.ts +6 -0
  414. package/shared/analyzer/stack.js +134 -141
  415. package/shared/analyzer/stack.js.map +1 -0
  416. package/shared/analyzer/tour.d.ts +2 -0
  417. package/shared/analyzer/tour.js +45 -53
  418. package/shared/analyzer/tour.js.map +1 -0
  419. package/shared/analyzer/util.d.ts +8 -0
  420. package/shared/analyzer/util.js +130 -76
  421. package/shared/analyzer/util.js.map +1 -0
  422. package/shared/analyzer/workflows.d.ts +8 -0
  423. package/shared/analyzer/workflows.js +139 -134
  424. package/shared/analyzer/workflows.js.map +1 -0
  425. package/shared/contracts.d.ts +250 -0
  426. package/shared/contracts.js +2 -0
  427. package/shared/contracts.js.map +1 -0
  428. package/shared/diagram/aiFacts.d.ts +35 -0
  429. package/shared/diagram/aiFacts.js +102 -105
  430. package/shared/diagram/aiFacts.js.map +1 -0
  431. package/shared/diagram/aiMermaid.d.ts +5 -0
  432. package/shared/diagram/aiMermaid.js +46 -45
  433. package/shared/diagram/aiMermaid.js.map +1 -0
  434. package/shared/diagram/atlas.d.ts +16 -0
  435. package/shared/diagram/atlas.js +51 -60
  436. package/shared/diagram/atlas.js.map +1 -0
  437. package/shared/diagram/mermaid.d.ts +43 -0
  438. package/shared/diagram/mermaid.js +348 -370
  439. package/shared/diagram/mermaid.js.map +1 -0
  440. package/shared/review/contracts.d.ts +95 -0
  441. package/shared/review/contracts.js +2 -0
  442. package/shared/review/contracts.js.map +1 -0
  443. package/shared/review/review.d.ts +10 -0
  444. package/shared/review/review.js +184 -0
  445. package/shared/review/review.js.map +1 -0
  446. package/shared/search/query.d.ts +32 -0
  447. package/shared/search/query.js +395 -388
  448. package/shared/search/query.js.map +1 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.js","sourceRoot":"","sources":["../../src/shared/analyzer/graph.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ImportEdge } from '../contracts.js';\n// Graph facts: entry points, hubs, orphans, cycles, fan-in/fan-out.\n// Pure functions over the scan result — no I/O here.\n\nimport { isTestPath, topFolderOf } from './pathUtil.js';\n\nconst ENTRY_NAMES = new Set([\n 'index', 'main', 'app', 'server', 'cli', 'manage', 'mod', '__main__',\n 'run', 'start', 'cmd',\n]);\n\nexport function computeFacts(scan, manifest: Record<string, any> = {}) {\n const { files, edges } = scan;\n const fanIn = new Map();\n const fanOut = new Map();\n const importers = new Map();\n const importsOf = new Map();\n\n for (const f of files) {\n fanIn.set(f.path, 0);\n fanOut.set(f.path, 0);\n importers.set(f.path, []);\n importsOf.set(f.path, []);\n }\n for (const e of edges) {\n if (!fanIn.has(e.to) || !fanOut.has(e.from)) continue;\n fanIn.set(e.to, fanIn.get(e.to) + 1);\n fanOut.set(e.from, fanOut.get(e.from) + 1);\n importers.get(e.to).push(e.from);\n importsOf.get(e.from).push(e.to);\n }\n\n const entrySet = new Set();\n for (const f of files) {\n const stem = (f.name || f.path || '').replace(/\\.[^.]+$/, '');\n if (ENTRY_NAMES.has(stem) || f.hasMain) entrySet.add(f.path);\n }\n for (const p of manifest.entryPoints || []) entrySet.add(p);\n\n // Tarjan is the most expensive thing in this function, and one run answers\n // both questions asked of it: which files sit in a cycle, and what the\n // largest cycles are. It used to run twice on identical input.\n const sccs = stronglyConnected(files.map((f) => f.path), edges);\n const multi = sccs.filter((scc) => scc.length > 1);\n\n const inCycle = new Set();\n for (const scc of multi) for (const p of scc) inCycle.add(p);\n\n const entries = files\n .filter((f) => entrySet.has(f.path))\n .map((f) => f.path)\n .sort();\n\n // A hub is a file other files depend on. The threshold is 2, not 3: in a\n // repo with 20 files, \"imported by two others\" *is* the most-depended-upon\n // file, and a threshold of 3 reported no hubs at all for a whole small project\n // — the map of a small repo is exactly where a hub is most useful. Two is the\n // lowest value that still means \"more than one other file reaches for this\".\n const hubs = files\n .map((f) => ({ path: f.path, fanIn: fanIn.get(f.path) || 0, fanOut: fanOut.get(f.path) || 0 }))\n .filter((h) => h.fanIn >= 2)\n .sort((a, b) => b.fanIn - a.fanIn);\n\n const orphans = files\n .filter((f) => (fanIn.get(f.path) || 0) === 0 && !entrySet.has(f.path) && !isTestPath(f.path))\n .map((f) => f.path)\n .sort();\n\n const cycles = multi\n .slice()\n .sort((a, b) => b.length - a.length)\n .slice(0, 10);\n\n // Collect all imported symbols per target file\n const importedSymbolsByTarget = new Map();\n const wildcards = new Set();\n for (const e of edges) {\n if (!e.to) continue;\n if (!importedSymbolsByTarget.has(e.to)) importedSymbolsByTarget.set(e.to, new Set());\n const set = importedSymbolsByTarget.get(e.to);\n if (!e.symbols || !e.symbols.length || e.symbols.includes('*')) {\n wildcards.add(e.to);\n } else {\n for (const s of e.symbols) set.add(s);\n }\n }\n\n const deadExports = [];\n for (const f of files) {\n if (!f.exports || !f.exports.length) continue;\n if (entrySet.has(f.path) || isTestPath(f.path) || wildcards.has(f.path)) continue;\n const importedSet = importedSymbolsByTarget.get(f.path);\n if (!importedSet || importedSet.size === 0) {\n for (const exp of f.exports) {\n deadExports.push({ file: f.path, name: exp.name, kind: exp.kind });\n }\n } else {\n for (const exp of f.exports) {\n if (!importedSet.has(exp.name)) {\n deadExports.push({ file: f.path, name: exp.name, kind: exp.kind });\n }\n }\n }\n }\n\n // Test coverage & untested hubs\n const testFiles = files.filter((f) => isTestPath(f.path));\n const testedSet = new Set();\n const testQueue = [];\n for (const tf of testFiles) {\n for (const target of importsOf.get(tf.path) || []) {\n if (!isTestPath(target) && !testedSet.has(target)) {\n testedSet.add(target);\n testQueue.push(target);\n }\n }\n }\n // Each file is enqueued once, so an index gives a complete O(V + E) walk.\n // The old 500-step ceiling silently undercounted coverage in large repos.\n for (let cursor = 0; cursor < testQueue.length; cursor++) {\n const curr = testQueue[cursor];\n for (const next of importsOf.get(curr) || []) {\n if (!isTestPath(next) && !testedSet.has(next)) {\n testedSet.add(next);\n testQueue.push(next);\n }\n }\n }\n const nonTestFiles = files.filter((f) => !isTestPath(f.path));\n const untestedHubs = hubs.filter((h) => !isTestPath(h.path) && !testedSet.has(h.path));\n const testCoverage = {\n testedCount: testedSet.size,\n totalNonTest: nonTestFiles.length,\n ratio: nonTestFiles.length ? Math.round((testedSet.size / nonTestFiles.length) * 100) : 100,\n };\n\n // Dependency drift\n const declaredDeps = new Set<string>([\n ...Object.keys(manifest.deps?.npm || {}),\n ...Object.keys(manifest.deps?.dev || {}),\n ...(manifest.deps?.pip || []),\n ...(manifest.deps?.go || []),\n ...(manifest.deps?.cargo || []),\n ]);\n const importedExternals = new Set<string>((scan.externals || []).map((x) => x.name));\n const unusedDeclared = [...declaredDeps].filter((d) => !importedExternals.has(d)).sort();\n const BUILTIN_MODULES = new Set([\n 'fs', 'path', 'http', 'https', 'url', 'crypto', 'os', 'stream', 'util',\n 'events', 'child_process', 'buffer', 'assert', 'net', 'zlib', 'tls', 'dns',\n 'perf_hooks', 'worker_threads',\n ]);\n const undeclaredImported = [...importedExternals]\n .filter((i) => !declaredDeps.has(i) && !BUILTIN_MODULES.has(i))\n .sort();\n const depsDrift = { unusedDeclared, undeclaredImported };\n\n const folderEdges = new Map();\n for (const e of edges) {\n const a = topFolderOf(e.from);\n const b = topFolderOf(e.to);\n if (a === b) continue;\n const key = a + '->' + b;\n folderEdges.set(key, (folderEdges.get(key) || 0) + 1);\n }\n\n const paths = files.map(f => f.path);\n const communitiesMap = louvainCommunities(paths, edges);\n const commGroups = new Map();\n for (const [n, c] of communitiesMap.entries()) {\n if (!commGroups.has(c)) commGroups.set(c, []);\n commGroups.get(c).push(n);\n }\n const communities = [...commGroups.entries()]\n .map(([id, members]) => ({ id, members, size: members.length }))\n .sort((a, b) => b.size - a.size);\n\n const betweennessResult = brandesBetweenness(paths, edges);\n const betweenness = Object.fromEntries(betweennessResult.map);\n\n return {\n communities,\n betweenness,\n // Whether `betweenness` above is a real measurement or all zeros\n // because the graph was over the Brandes cap. The UI uses this the\n // same way it uses `health.blastExact`: it shows an honest\n // \"not computed for repos of this size\" instead of pretending the\n // zeros are a finding.\n betweennessExact: betweennessResult.exact,\n fanIn: Object.fromEntries(fanIn),\n fanOut: Object.fromEntries(fanOut),\n importers: Object.fromEntries(importers),\n importsOf: Object.fromEntries(importsOf),\n entries,\n hubs,\n orphans,\n cycles,\n inCycle: [...inCycle],\n deadExports,\n testCoverage,\n untestedHubs,\n depsDrift,\n folderEdges: [...folderEdges.entries()].map(([key, count]) => {\n const [from, to] = key.split('->');\n return { from, to, count };\n }),\n entrySet: entries,\n };\n}\n\n// Tarjan's strongly connected components, iterative so deep graphs don't\n// blow the stack.\nfunction stronglyConnected(nodes: string[], edges: ImportEdge[]) {\n const adj = new Map(nodes.map((n) => [n, []]));\n for (const e of edges) {\n if (adj.has(e.from)) adj.get(e.from).push(e.to);\n }\n const index = new Map();\n const low = new Map();\n const onStack = new Set();\n const stack = [];\n const result = [];\n let counter = 0;\n\n for (const start of nodes) {\n if (index.has(start)) continue;\n const work: Array<[string, number]> = [[start, 0]];\n while (work.length) {\n const [v, pi] = work[work.length - 1];\n if (pi === 0) {\n index.set(v, counter);\n low.set(v, counter);\n counter++;\n stack.push(v);\n onStack.add(v);\n }\n const children = adj.get(v) || [];\n if (pi < children.length) {\n work[work.length - 1][1] = pi + 1;\n const w = children[pi];\n if (!index.has(w)) {\n work.push([w, 0]);\n } else if (onStack.has(w)) {\n low.set(v, Math.min(low.get(v), index.get(w)));\n }\n } else {\n work.pop();\n if (work.length) {\n const parent = work[work.length - 1][0];\n low.set(parent, Math.min(low.get(parent), low.get(v)));\n }\n if (low.get(v) === index.get(v)) {\n const scc = [];\n let w;\n do {\n w = stack.pop();\n onStack.delete(w);\n scc.push(w);\n } while (w !== v);\n result.push(scc);\n }\n }\n }\n }\n return result;\n}\n\n// Lookup shapes for the render loops.\n//\n// `facts` is plain data on purpose — it is serialized to JSON and handed to the\n// browser, so `entries`, `inCycle` and `hubs` have to travel as arrays. But the\n// UI asks \"is this file in a cycle?\" once per file per redraw, and an array\n// answers that in O(n): drawing a 2,000-file map turned into four million string\n// comparisons. This builds the Sets and Maps once per facts object and\n// remembers them in a WeakMap, so the index costs nothing on the second call\n// and is collected the moment the scan it describes is dropped.\n//\n// It assumes nobody mutates `facts` after computing it. Nothing does — the\n// engine returns it and every consumer reads.\nconst INDEXES = new WeakMap();\n\nexport function factIndex(facts) {\n let index = INDEXES.get(facts);\n if (index) return index;\n index = {\n entries: new Set(facts.entries || []),\n inCycle: new Set(facts.inCycle || []),\n hubs: new Map((facts.hubs || []).map((h) => [h.path, h])),\n };\n INDEXES.set(facts, index);\n return index;\n}\n\nexport function roleOf(path, facts) {\n if (isTestPath(path)) return 'test';\n const index = factIndex(facts);\n if (index.entries.has(path)) return 'entry';\n const hub = index.hubs.get(path);\n if (hub && hub.fanIn >= 5) return 'hub';\n const fin = facts.fanIn[path] || 0;\n const fout = facts.fanOut[path] || 0;\n if (fout === 0 && fin > 0) return 'leaf';\n if (/config|settings|\\.json$|\\.ya?ml$|\\.toml$/.test(path)) return 'config';\n return 'module';\n}\n\n// Is this file part of an import cycle? Same answer as\n// `facts.inCycle.includes(path)`, without the scan.\nexport function inCycle(path, facts) {\n return factIndex(facts).inCycle.has(path);\n}\n\n// The same trick for the scan itself. `scan.files.find((f) => f.path === p)` and\n// `scan.files.filter((f) => f.dir === d)` were written a dozen times across the\n// engine and the UI, both inside per-file loops — the docs generator alone ran\n// the first one once per file per folder. One pass builds both lookups.\n//\n// `byDir` hands back the same array to every caller, in `scan.files` order.\n// Treat it as read-only: copy before sorting.\nconst SCAN_INDEXES = new WeakMap();\nconst NO_FILES = Object.freeze([]);\n\nexport function scanIndex(scan) {\n let index = SCAN_INDEXES.get(scan);\n if (index) return index;\n const byPath = new Map();\n const byDir = new Map();\n for (const f of scan.files || []) {\n byPath.set(f.path, f);\n const bucket = byDir.get(f.dir);\n if (bucket) bucket.push(f);\n else byDir.set(f.dir, [f]);\n }\n index = {\n byPath,\n byDir,\n fileAt: (path) => byPath.get(path) || null,\n filesIn: (dir) => byDir.get(dir) || NO_FILES,\n };\n SCAN_INDEXES.set(scan, index);\n return index;\n}\n\nfunction louvainCommunities(nodes: string[], edges: ImportEdge[]) {\n let communities = new Map(nodes.map(n => [n, n]));\n let tot = new Map(nodes.map(n => [n, 0]));\n let inC = new Map(nodes.map(n => [n, 0]));\n let k = new Map(nodes.map(n => [n, 0]));\n let m2 = 0;\n \n const adj = new Map(nodes.map(n => [n, []]));\n for (const e of edges) {\n if (!adj.has(e.from)) adj.set(e.from, []);\n adj.get(e.from).push(e.to);\n k.set(e.from, (k.get(e.from) || 0) + 1);\n k.set(e.to, (k.get(e.to) || 0) + 1);\n m2 += 2;\n }\n if (m2 === 0) return communities;\n\n for (const n of nodes) tot.set(n, k.get(n));\n\n // Eight passes is enough for any practical graph to settle. Three was\n // the early limit and worked for small repos, but on denser graphs the\n // modularity gain was still climbing at iteration three. The early-exit\n // (`improved === false`) keeps the cost bounded on graphs that converge\n // quickly, so this is not a free pass on every scan — it is a ceiling.\n let iters = 0;\n let improved = true;\n while (iters < 8 && improved) {\n improved = false;\n for (const u of nodes) {\n const c_u = communities.get(u);\n const k_u = k.get(u);\n \n const counts = new Map();\n for (const v of (adj.get(u) || [])) {\n const c_v = communities.get(v);\n counts.set(c_v, (counts.get(c_v) || 0) + 1);\n }\n \n let best_c = c_u;\n let max_gain = 0;\n \n for (const [c_v, weight] of counts.entries()) {\n if (c_v === c_u) continue;\n const tot_c = tot.get(c_v);\n const gain = weight - (k_u * tot_c) / m2;\n if (gain > max_gain) {\n max_gain = gain;\n best_c = c_v;\n }\n }\n \n if (best_c !== c_u) {\n tot.set(c_u, tot.get(c_u) - k_u);\n tot.set(best_c, tot.get(best_c) + k_u);\n communities.set(u, best_c);\n improved = true;\n }\n }\n iters++;\n }\n return communities;\n}\n\n// Brandes's algorithm. The old return was just a Map of zeros when the\n// graph had more than 1,000 nodes, which is honest about the cost (O(V·E)\n// in the unweighted case) but dishonest about what the consumer is looking\n// at: a row of zeros reads like a real measurement. The wrapper now returns\n// `{ map, exact }` so the consumer can show \"betweenness was not computed\n// for repos over 1,000 files\" the way the health panel shows\n// `blastExact: false` next to a fan-in fallback.\nfunction brandesBetweenness(nodes: string[], edges: ImportEdge[]) {\n const cb = new Map(nodes.map(n => [n, 0]));\n if (nodes.length > 1000) return { map: cb, exact: false };\n\n const adj = new Map(nodes.map(n => [n, []]));\n for (const e of edges) {\n if (adj.has(e.from)) adj.get(e.from).push(e.to);\n }\n\n for (const s of nodes) {\n const S = [];\n const P = new Map(nodes.map(n => [n, []]));\n const sigma = new Map(nodes.map(n => [n, 0]));\n sigma.set(s, 1);\n const d = new Map(nodes.map(n => [n, -1]));\n d.set(s, 0);\n const Q = [s];\n\n while (Q.length > 0) {\n const v = Q.shift();\n S.push(v);\n for (const w of (adj.get(v) || [])) {\n if (d.get(w) < 0) {\n d.set(w, d.get(v) + 1);\n Q.push(w);\n }\n if (d.get(w) === d.get(v) + 1) {\n sigma.set(w, sigma.get(w) + sigma.get(v));\n P.get(w).push(v);\n }\n }\n }\n\n const delta = new Map(nodes.map(n => [n, 0]));\n while (S.length > 0) {\n const w = S.pop();\n for (const v of P.get(w)) {\n delta.set(v, delta.get(v) + (sigma.get(v) / sigma.get(w)) * (1 + delta.get(w)));\n }\n if (w !== s) {\n cb.set(w, cb.get(w) + delta.get(w));\n }\n }\n }\n\n let max = 0;\n for (const val of cb.values()) if (val > max) max = val;\n if (max > 0) {\n for (const [k, v] of cb.entries()) cb.set(k, v / max);\n }\n\n return { map: cb, exact: true };\n}\n"]}
@@ -0,0 +1,33 @@
1
+ export declare function analyzeHealth(scan: any, facts: any): {
2
+ score: number;
3
+ grade: string;
4
+ perFile: any[];
5
+ breakdown: any[];
6
+ blastExact: boolean;
7
+ totals: {
8
+ crit: number;
9
+ high: number;
10
+ avgCx: number;
11
+ orphanRatio: number;
12
+ cycles: number;
13
+ };
14
+ techDebtRatio?: undefined;
15
+ effortHours?: undefined;
16
+ debtCategory?: undefined;
17
+ } | {
18
+ score: number;
19
+ grade: string;
20
+ perFile: any;
21
+ breakdown: any[];
22
+ blastExact: boolean;
23
+ totals: {
24
+ crit: any;
25
+ high: any;
26
+ avgCx: number;
27
+ orphanRatio: number;
28
+ cycles: any;
29
+ };
30
+ techDebtRatio: number;
31
+ effortHours: number;
32
+ debtCategory: string;
33
+ };
@@ -1,215 +1,219 @@
1
1
  // The advanced analysis engine: graph centrality (PageRank), blast radius
2
2
  // (transitive dependents), instability (Martin's Ce/(Ca+Ce)), a per-file risk
3
3
  // score, and a repo health grade. Pure — runs in Node and the browser.
4
-
5
4
  const clamp = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
6
-
7
5
  export function analyzeHealth(scan, facts) {
8
- const files = scan.files;
9
- const paths = files.map((f) => f.path);
10
- const n = paths.length;
11
- // A folder with no code we recognize. The shape has to match the real return
12
- // or the Health panel throws on `health.breakdown.length`.
13
- if (!n) {
14
- return {
15
- score: 100, grade: 'A', perFile: [], breakdown: [], blastExact: true,
16
- totals: { crit: 0, high: 0, avgCx: 0, orphanRatio: 0, cycles: 0 },
17
- };
18
- }
19
-
20
- const pr = pageRank(paths, scan.edges);
21
- let prMax = 1e-9;
22
- for (const p of paths) {
23
- if (pr[p] > prMax) prMax = pr[p];
24
- }
25
-
26
- // Blast radius = number of distinct files that transitively depend on me.
27
- // Above 2,500 files the condensation gets expensive, so we fall back to
28
- // plain fan-in — a different measurement wearing the same name. `blastExact`
29
- // travels with the result so the UI can stop calling it a blast radius.
30
- const blast = n <= 2500 ? blastRadius(paths, scan.edges) : null;
31
- const inCycle = new Set(facts.inCycle);
32
-
33
- const perFile = files.map((f) => {
34
- const p = f.path;
35
- const ca = facts.fanIn[p] || 0;
36
- const ce = facts.fanOut[p] || 0;
37
- const instability = ca + ce === 0 ? 0 : ce / (ca + ce);
38
- const cx = f.complexity || 1;
39
- const loc = f.loc || f.size || 0;
40
- const centrality = (pr[p] || 0) / prMax;
41
- const risk = clamp(
42
- Math.round(
43
- 34 * centrality + // how load-bearing this file is
44
- 26 * Math.min(cx / 28, 1) + // how hard it is to change safely
45
- 20 * (inCycle.has(p) ? 1 : 0) + // cycles are the sharpest edge
46
- 12 * Math.min(loc / 900, 1) + // bulk alone slows reading
47
- 8 * instability // high efferent → change ripples outward
48
- ),
49
- 0,
50
- 100
51
- );
52
- return {
53
- path: p, name: f.name, risk,
54
- centrality: Math.round(centrality * 100) / 100,
55
- blast: blast ? blast[p] : ca,
56
- instability: Math.round(instability * 100) / 100,
57
- complexity: cx, loc, fanIn: ca, fanOut: ce, inCycle: inCycle.has(p),
6
+ const files = scan.files;
7
+ const paths = files.map((f) => f.path);
8
+ const n = paths.length;
9
+ // A folder with no code we recognize. The shape has to match the real return
10
+ // or the Health panel throws on `health.breakdown.length`.
11
+ if (!n) {
12
+ return {
13
+ score: 100, grade: 'A', perFile: [], breakdown: [], blastExact: true,
14
+ totals: { crit: 0, high: 0, avgCx: 0, orphanRatio: 0, cycles: 0 },
15
+ };
16
+ }
17
+ const pr = pageRank(paths, scan.edges);
18
+ let prMax = 1e-9;
19
+ for (const p of paths) {
20
+ if (pr[p] > prMax)
21
+ prMax = pr[p];
22
+ }
23
+ // Blast radius = number of distinct files that transitively depend on me.
24
+ // Above 2,500 files the condensation gets expensive, so we fall back to
25
+ // plain fan-in — a different measurement wearing the same name. `blastExact`
26
+ // travels with the result so the UI can stop calling it a blast radius.
27
+ const blast = n <= 2500 ? blastRadius(paths, scan.edges) : null;
28
+ const inCycle = new Set(facts.inCycle);
29
+ const perFile = files.map((f) => {
30
+ const p = f.path;
31
+ const ca = facts.fanIn[p] || 0;
32
+ const ce = facts.fanOut[p] || 0;
33
+ const instability = ca + ce === 0 ? 0 : ce / (ca + ce);
34
+ const cx = f.complexity || 1;
35
+ const loc = f.loc || f.size || 0;
36
+ const centrality = (pr[p] || 0) / prMax;
37
+ const risk = clamp(Math.round(34 * centrality + // how load-bearing this file is
38
+ 26 * Math.min(cx / 28, 1) + // how hard it is to change safely
39
+ 20 * (inCycle.has(p) ? 1 : 0) + // cycles are the sharpest edge
40
+ 12 * Math.min(loc / 900, 1) + // bulk alone slows reading
41
+ 8 * instability // high efferent → change ripples outward
42
+ ), 0, 100);
43
+ return {
44
+ path: p, name: f.name, risk,
45
+ centrality: Math.round(centrality * 100) / 100,
46
+ blast: blast ? blast[p] : ca,
47
+ instability: Math.round(instability * 100) / 100,
48
+ complexity: cx, loc, fanIn: ca, fanOut: ce, inCycle: inCycle.has(p),
49
+ };
50
+ });
51
+ perFile.sort((a, b) => b.risk - a.risk);
52
+ const crit = perFile.filter((f) => f.risk >= 70).length;
53
+ const high = perFile.filter((f) => f.risk >= 50 && f.risk < 70).length;
54
+ const avgCx = perFile.reduce((s, f) => s + f.complexity, 0) / n;
55
+ const orphanRatio = (facts.orphans.length || 0) / n;
56
+ // The score, itemized — so the grade can explain itself.
57
+ const breakdown = [];
58
+ let score = 100;
59
+ const take = (points, label) => {
60
+ const p = Math.round(points);
61
+ if (p >= 1) {
62
+ score -= p;
63
+ breakdown.push({ label, points: -p });
64
+ }
58
65
  };
59
- });
60
- perFile.sort((a, b) => b.risk - a.risk);
61
-
62
- const crit = perFile.filter((f) => f.risk >= 70).length;
63
- const high = perFile.filter((f) => f.risk >= 50 && f.risk < 70).length;
64
- const avgCx = perFile.reduce((s, f) => s + f.complexity, 0) / n;
65
- const orphanRatio = (facts.orphans.length || 0) / n;
66
-
67
- // The score, itemized — so the grade can explain itself.
68
- const breakdown = [];
69
- let score = 100;
70
- const take = (points, label) => {
71
- const p = Math.round(points);
72
- if (p >= 1) { score -= p; breakdown.push({ label, points: -p }); }
73
- };
74
- const cycleCount = facts.cycles?.length || 0;
75
- take(cycleCount * 4, `${cycleCount} circular ${cycleCount === 1 ? 'dependency' : 'dependencies'}`);
76
- take(crit * 4 + high * 2, `${crit} critical + ${high} high-risk file${crit + high === 1 ? '' : 's'}`);
77
- take(Math.max(0, avgCx - 6) * 2, `average complexity ${Math.round(avgCx * 10) / 10} (over 6)`);
78
- take(orphanRatio * 25, `${Math.round(orphanRatio * 100)}% of files unconnected`);
79
- score = Math.max(0, Math.round(score));
80
- const grade = score >= 90 ? 'A' : score >= 80 ? 'B' : score >= 70 ? 'C' : score >= 60 ? 'D' : 'F';
81
- let lowMI = 0;
82
- let totalEffort = 0;
83
- for (const f of files) {
84
- if (f.maintainabilityIndex < 65) lowMI++;
85
- if (f.effort) totalEffort += f.effort;
86
- }
87
- const techDebtRatio = n ? lowMI / n : 0;
88
- const effortHours = totalEffort / 3600;
89
- let debtCategory = 'low';
90
- if (techDebtRatio > 0.5) debtCategory = 'critical';
91
- else if (techDebtRatio > 0.25) debtCategory = 'high';
92
- else if (techDebtRatio > 0.10) debtCategory = 'moderate';
93
-
94
-
66
+ const cycleCount = facts.cycles?.length || 0;
67
+ take(cycleCount * 4, `${cycleCount} circular ${cycleCount === 1 ? 'dependency' : 'dependencies'}`);
68
+ take(crit * 4 + high * 2, `${crit} critical + ${high} high-risk file${crit + high === 1 ? '' : 's'}`);
69
+ take(Math.max(0, avgCx - 6) * 2, `average complexity ${Math.round(avgCx * 10) / 10} (over 6)`);
70
+ take(orphanRatio * 25, `${Math.round(orphanRatio * 100)}% of files unconnected`);
71
+ score = Math.max(0, Math.round(score));
72
+ const grade = score >= 90 ? 'A' : score >= 80 ? 'B' : score >= 70 ? 'C' : score >= 60 ? 'D' : 'F';
73
+ let lowMI = 0;
74
+ let totalEffort = 0;
75
+ for (const f of files) {
76
+ if (f.maintainabilityIndex < 65)
77
+ lowMI++;
78
+ if (f.effort)
79
+ totalEffort += f.effort;
80
+ }
81
+ const techDebtRatio = n ? lowMI / n : 0;
82
+ const effortHours = totalEffort / 3600;
83
+ let debtCategory = 'low';
84
+ if (techDebtRatio > 0.5)
85
+ debtCategory = 'critical';
86
+ else if (techDebtRatio > 0.25)
87
+ debtCategory = 'high';
88
+ else if (techDebtRatio > 0.10)
89
+ debtCategory = 'moderate';
95
90
  return { score, grade, perFile, breakdown, blastExact: Boolean(blast), totals: { crit, high, avgCx: Math.round(avgCx * 10) / 10, orphanRatio, cycles: facts.cycles.length || 0 }, techDebtRatio, effortHours, debtCategory };
96
91
  }
97
-
98
92
  // Importance over the directed import graph: edge a→b (a imports b) means
99
93
  // rank flows to b — the files everything leans on rise to the top.
100
94
  function pageRank(paths, edges) {
101
- const n = paths.length;
102
- const idx = Object.fromEntries(paths.map((p, i) => [p, i]));
103
- const adj = Array.from({ length: n }, () => []);
104
- const out = new Array(n).fill(0);
105
- for (const e of edges) {
106
- const a = idx[e.from];
107
- const b = idx[e.to];
108
- if (a == null || b == null) continue;
109
- adj[a].push(b);
110
- out[a]++;
111
- }
112
- let rank = new Array(n).fill(1 / n);
113
- const d = 0.85;
114
- for (let it = 0; it < 24; it++) {
115
- const next = new Array(n).fill((1 - d) / n);
116
- for (let a = 0; a < n; a++) {
117
- const share = (rank[a] * d) / (out[a] || 1);
118
- for (const b of adj[a]) next[b] += share;
95
+ const n = paths.length;
96
+ const idx = Object.fromEntries(paths.map((p, i) => [p, i]));
97
+ const adj = Array.from({ length: n }, () => []);
98
+ const out = new Array(n).fill(0);
99
+ for (const e of edges) {
100
+ const a = idx[e.from];
101
+ const b = idx[e.to];
102
+ if (a == null || b == null)
103
+ continue;
104
+ adj[a].push(b);
105
+ out[a]++;
119
106
  }
120
- rank = next;
121
- }
122
- const map = {};
123
- paths.forEach((p, i) => (map[p] = rank[i]));
124
- return map;
107
+ let rank = new Array(n).fill(1 / n);
108
+ const d = 0.85;
109
+ for (let it = 0; it < 24; it++) {
110
+ const next = new Array(n).fill((1 - d) / n);
111
+ for (let a = 0; a < n; a++) {
112
+ const share = (rank[a] * d) / (out[a] || 1);
113
+ for (const b of adj[a])
114
+ next[b] += share;
115
+ }
116
+ rank = next;
117
+ }
118
+ const map = {};
119
+ paths.forEach((p, i) => (map[p] = rank[i]));
120
+ return map;
125
121
  }
126
-
127
122
  // Distinct transitive dependents per node, computed exactly via strongly
128
123
  // connected components so cycles share one reachable set.
129
124
  function blastRadius(paths, edges) {
130
- const n = paths.length;
131
- const idx = Object.fromEntries(paths.map((p, i) => [p, i]));
132
- // Reverse the graph: walk from a file to everything that imports it.
133
- const radj = Array.from({ length: n }, () => []);
134
- for (const e of edges) {
135
- const a = idx[e.from];
136
- const b = idx[e.to];
137
- if (a == null || b == null) continue;
138
- radj[b].push(a);
139
- }
140
- const { comp, compCount } = tarjan(n, radj);
141
- const compSize = new Array(compCount).fill(0);
142
- const compAdj = Array.from({ length: compCount }, () => new Set());
143
- for (let v = 0; v < n; v++) {
144
- compSize[comp[v]]++;
145
- for (const w of radj[v]) if (comp[w] !== comp[v]) compAdj[comp[v]].add(comp[w]);
146
- }
147
- const memo = new Map();
148
- const reach = (c) => {
149
- if (memo.has(c)) return memo.get(c);
150
- const set = new Set([c]);
151
- for (const s of compAdj[c]) for (const x of reach(s)) set.add(x);
152
- memo.set(c, set);
153
- return set;
154
- };
155
- const blast = {};
156
- paths.forEach((p, i) => {
157
- let count = 0;
158
- for (const c of reach(comp[i])) count += compSize[c];
159
- blast[p] = count - compSize[comp[i]]; // exclude self
160
- });
161
- return blast;
125
+ const n = paths.length;
126
+ const idx = Object.fromEntries(paths.map((p, i) => [p, i]));
127
+ // Reverse the graph: walk from a file to everything that imports it.
128
+ const radj = Array.from({ length: n }, () => []);
129
+ for (const e of edges) {
130
+ const a = idx[e.from];
131
+ const b = idx[e.to];
132
+ if (a == null || b == null)
133
+ continue;
134
+ radj[b].push(a);
135
+ }
136
+ const { comp, compCount } = tarjan(n, radj);
137
+ const compSize = new Array(compCount).fill(0);
138
+ const compAdj = Array.from({ length: compCount }, () => new Set());
139
+ for (let v = 0; v < n; v++) {
140
+ compSize[comp[v]]++;
141
+ for (const w of radj[v])
142
+ if (comp[w] !== comp[v])
143
+ compAdj[comp[v]].add(comp[w]);
144
+ }
145
+ const memo = new Map();
146
+ const reach = (c) => {
147
+ if (memo.has(c))
148
+ return memo.get(c);
149
+ const set = new Set([c]);
150
+ for (const s of compAdj[c])
151
+ for (const x of reach(s))
152
+ set.add(x);
153
+ memo.set(c, set);
154
+ return set;
155
+ };
156
+ const blast = {};
157
+ paths.forEach((p, i) => {
158
+ let count = 0;
159
+ for (const c of reach(comp[i]))
160
+ count += compSize[c];
161
+ blast[p] = count - compSize[comp[i]]; // exclude self
162
+ });
163
+ return blast;
162
164
  }
163
-
164
165
  // Iterative Tarjan (no recursion limit on long chains).
165
166
  function tarjan(n, adj) {
166
- const comp = new Array(n).fill(-1);
167
- const index = new Array(n).fill(-1);
168
- const low = new Array(n).fill(0);
169
- const onStack = new Array(n).fill(false);
170
- const stack = [];
171
- let idx = 0;
172
- let compCount = 0;
173
- for (let s = 0; s < n; s++) {
174
- if (index[s] !== -1) continue;
175
- const work = [[s, 0]];
176
- while (work.length) {
177
- const top = work[work.length - 1];
178
- const v = top[0];
179
- let i = top[1];
180
- if (i === 0) {
181
- index[v] = low[v] = idx++;
182
- stack.push(v);
183
- onStack[v] = true;
184
- }
185
- let pushed = false;
186
- for (; i < adj[v].length; i++) {
187
- const w = adj[v][i];
188
- if (index[w] === -1) {
189
- top[1] = i + 1;
190
- work.push([w, 0]);
191
- pushed = true;
192
- break;
167
+ const comp = new Array(n).fill(-1);
168
+ const index = new Array(n).fill(-1);
169
+ const low = new Array(n).fill(0);
170
+ const onStack = new Array(n).fill(false);
171
+ const stack = [];
172
+ let idx = 0;
173
+ let compCount = 0;
174
+ for (let s = 0; s < n; s++) {
175
+ if (index[s] !== -1)
176
+ continue;
177
+ const work = [[s, 0]];
178
+ while (work.length) {
179
+ const top = work[work.length - 1];
180
+ const v = top[0];
181
+ let i = top[1];
182
+ if (i === 0) {
183
+ index[v] = low[v] = idx++;
184
+ stack.push(v);
185
+ onStack[v] = true;
186
+ }
187
+ let pushed = false;
188
+ for (; i < adj[v].length; i++) {
189
+ const w = adj[v][i];
190
+ if (index[w] === -1) {
191
+ top[1] = i + 1;
192
+ work.push([w, 0]);
193
+ pushed = true;
194
+ break;
195
+ }
196
+ if (onStack[w])
197
+ low[v] = Math.min(low[v], index[w]);
198
+ }
199
+ if (pushed)
200
+ continue;
201
+ if (low[v] === index[v]) {
202
+ let w;
203
+ do {
204
+ w = stack.pop();
205
+ onStack[w] = false;
206
+ comp[w] = compCount;
207
+ } while (w !== v);
208
+ compCount++;
209
+ }
210
+ work.pop();
211
+ if (work.length) {
212
+ const parent = work[work.length - 1][0];
213
+ low[parent] = Math.min(low[parent], low[v]);
214
+ }
193
215
  }
194
- if (onStack[w]) low[v] = Math.min(low[v], index[w]);
195
- }
196
- if (pushed) continue;
197
- if (low[v] === index[v]) {
198
- let w;
199
- do {
200
- w = stack.pop();
201
- onStack[w] = false;
202
- comp[w] = compCount;
203
- } while (w !== v);
204
- compCount++;
205
- }
206
- work.pop();
207
- if (work.length) {
208
- const parent = work[work.length - 1][0];
209
- low[parent] = Math.min(low[parent], low[v]);
210
- }
211
216
  }
212
- }
213
- return { comp, compCount };
217
+ return { comp, compCount };
214
218
  }
215
-
219
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/shared/analyzer/health.ts"],"names":[],"mappings":"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","sourcesContent":["// The advanced analysis engine: graph centrality (PageRank), blast radius\n// (transitive dependents), instability (Martin's Ce/(Ca+Ce)), a per-file risk\n// score, and a repo health grade. Pure — runs in Node and the browser.\n\nconst clamp = (v, lo, hi) => Math.max(lo, Math.min(hi, v));\n\nexport function analyzeHealth(scan, facts) {\n const files = scan.files;\n const paths = files.map((f) => f.path);\n const n = paths.length;\n // A folder with no code we recognize. The shape has to match the real return\n // or the Health panel throws on `health.breakdown.length`.\n if (!n) {\n return {\n score: 100, grade: 'A', perFile: [], breakdown: [], blastExact: true,\n totals: { crit: 0, high: 0, avgCx: 0, orphanRatio: 0, cycles: 0 },\n };\n }\n\n const pr = pageRank(paths, scan.edges);\n let prMax = 1e-9;\n for (const p of paths) {\n if (pr[p] > prMax) prMax = pr[p];\n }\n\n // Blast radius = number of distinct files that transitively depend on me.\n // Above 2,500 files the condensation gets expensive, so we fall back to\n // plain fan-in — a different measurement wearing the same name. `blastExact`\n // travels with the result so the UI can stop calling it a blast radius.\n const blast = n <= 2500 ? blastRadius(paths, scan.edges) : null;\n const inCycle = new Set(facts.inCycle);\n\n const perFile = files.map((f) => {\n const p = f.path;\n const ca = facts.fanIn[p] || 0;\n const ce = facts.fanOut[p] || 0;\n const instability = ca + ce === 0 ? 0 : ce / (ca + ce);\n const cx = f.complexity || 1;\n const loc = f.loc || f.size || 0;\n const centrality = (pr[p] || 0) / prMax;\n const risk = clamp(\n Math.round(\n 34 * centrality + // how load-bearing this file is\n 26 * Math.min(cx / 28, 1) + // how hard it is to change safely\n 20 * (inCycle.has(p) ? 1 : 0) + // cycles are the sharpest edge\n 12 * Math.min(loc / 900, 1) + // bulk alone slows reading\n 8 * instability // high efferent → change ripples outward\n ),\n 0,\n 100\n );\n return {\n path: p, name: f.name, risk,\n centrality: Math.round(centrality * 100) / 100,\n blast: blast ? blast[p] : ca,\n instability: Math.round(instability * 100) / 100,\n complexity: cx, loc, fanIn: ca, fanOut: ce, inCycle: inCycle.has(p),\n };\n });\n perFile.sort((a, b) => b.risk - a.risk);\n\n const crit = perFile.filter((f) => f.risk >= 70).length;\n const high = perFile.filter((f) => f.risk >= 50 && f.risk < 70).length;\n const avgCx = perFile.reduce((s, f) => s + f.complexity, 0) / n;\n const orphanRatio = (facts.orphans.length || 0) / n;\n\n // The score, itemized — so the grade can explain itself.\n const breakdown = [];\n let score = 100;\n const take = (points, label) => {\n const p = Math.round(points);\n if (p >= 1) { score -= p; breakdown.push({ label, points: -p }); }\n };\n const cycleCount = facts.cycles?.length || 0;\n take(cycleCount * 4, `${cycleCount} circular ${cycleCount === 1 ? 'dependency' : 'dependencies'}`);\n take(crit * 4 + high * 2, `${crit} critical + ${high} high-risk file${crit + high === 1 ? '' : 's'}`);\n take(Math.max(0, avgCx - 6) * 2, `average complexity ${Math.round(avgCx * 10) / 10} (over 6)`);\n take(orphanRatio * 25, `${Math.round(orphanRatio * 100)}% of files unconnected`);\n score = Math.max(0, Math.round(score));\n const grade = score >= 90 ? 'A' : score >= 80 ? 'B' : score >= 70 ? 'C' : score >= 60 ? 'D' : 'F';\n let lowMI = 0;\n let totalEffort = 0;\n for (const f of files) {\n if (f.maintainabilityIndex < 65) lowMI++;\n if (f.effort) totalEffort += f.effort;\n }\n const techDebtRatio = n ? lowMI / n : 0;\n const effortHours = totalEffort / 3600;\n let debtCategory = 'low';\n if (techDebtRatio > 0.5) debtCategory = 'critical';\n else if (techDebtRatio > 0.25) debtCategory = 'high';\n else if (techDebtRatio > 0.10) debtCategory = 'moderate';\n\n\n return { score, grade, perFile, breakdown, blastExact: Boolean(blast), totals: { crit, high, avgCx: Math.round(avgCx * 10) / 10, orphanRatio, cycles: facts.cycles.length || 0 }, techDebtRatio, effortHours, debtCategory };\n}\n\n// Importance over the directed import graph: edge a→b (a imports b) means\n// rank flows to b — the files everything leans on rise to the top.\nfunction pageRank(paths, edges) {\n const n = paths.length;\n const idx = Object.fromEntries(paths.map((p, i) => [p, i]));\n const adj = Array.from({ length: n }, () => []);\n const out = new Array(n).fill(0);\n for (const e of edges) {\n const a = idx[e.from];\n const b = idx[e.to];\n if (a == null || b == null) continue;\n adj[a].push(b);\n out[a]++;\n }\n let rank = new Array(n).fill(1 / n);\n const d = 0.85;\n for (let it = 0; it < 24; it++) {\n const next = new Array(n).fill((1 - d) / n);\n for (let a = 0; a < n; a++) {\n const share = (rank[a] * d) / (out[a] || 1);\n for (const b of adj[a]) next[b] += share;\n }\n rank = next;\n }\n const map: Record<string, any> = {};\n paths.forEach((p, i) => (map[p] = rank[i]));\n return map;\n}\n\n// Distinct transitive dependents per node, computed exactly via strongly\n// connected components so cycles share one reachable set.\nfunction blastRadius(paths, edges) {\n const n = paths.length;\n const idx = Object.fromEntries(paths.map((p, i) => [p, i]));\n // Reverse the graph: walk from a file to everything that imports it.\n const radj = Array.from({ length: n }, () => []);\n for (const e of edges) {\n const a = idx[e.from];\n const b = idx[e.to];\n if (a == null || b == null) continue;\n radj[b].push(a);\n }\n const { comp, compCount } = tarjan(n, radj);\n const compSize = new Array(compCount).fill(0);\n const compAdj = Array.from({ length: compCount }, () => new Set());\n for (let v = 0; v < n; v++) {\n compSize[comp[v]]++;\n for (const w of radj[v]) if (comp[w] !== comp[v]) compAdj[comp[v]].add(comp[w]);\n }\n const memo = new Map();\n const reach = (c) => {\n if (memo.has(c)) return memo.get(c);\n const set = new Set([c]);\n for (const s of compAdj[c]) for (const x of reach(s)) set.add(x);\n memo.set(c, set);\n return set;\n };\n const blast: Record<string, any> = {};\n paths.forEach((p, i) => {\n let count = 0;\n for (const c of reach(comp[i])) count += compSize[c];\n blast[p] = count - compSize[comp[i]]; // exclude self\n });\n return blast;\n}\n\n// Iterative Tarjan (no recursion limit on long chains).\nfunction tarjan(n, adj) {\n const comp = new Array(n).fill(-1);\n const index = new Array(n).fill(-1);\n const low = new Array(n).fill(0);\n const onStack = new Array(n).fill(false);\n const stack = [];\n let idx = 0;\n let compCount = 0;\n for (let s = 0; s < n; s++) {\n if (index[s] !== -1) continue;\n const work = [[s, 0]];\n while (work.length) {\n const top = work[work.length - 1];\n const v = top[0];\n let i = top[1];\n if (i === 0) {\n index[v] = low[v] = idx++;\n stack.push(v);\n onStack[v] = true;\n }\n let pushed = false;\n for (; i < adj[v].length; i++) {\n const w = adj[v][i];\n if (index[w] === -1) {\n top[1] = i + 1;\n work.push([w, 0]);\n pushed = true;\n break;\n }\n if (onStack[w]) low[v] = Math.min(low[v], index[w]);\n }\n if (pushed) continue;\n if (low[v] === index[v]) {\n let w;\n do {\n w = stack.pop();\n onStack[w] = false;\n comp[w] = compCount;\n } while (w !== v);\n compCount++;\n }\n work.pop();\n if (work.length) {\n const parent = work[work.length - 1][0];\n low[parent] = Math.min(low[parent], low[v]);\n }\n }\n }\n return { comp, compCount };\n}\n\n"]}
@@ -0,0 +1,29 @@
1
+ export declare function analyzeHistory(scan: any, commits: any, opts?: Record<string, any>): {
2
+ available: boolean;
3
+ commitCount: any;
4
+ totalCommits: any;
5
+ truncated: boolean;
6
+ commits: any;
7
+ authors: any[];
8
+ firstCommitAt: any;
9
+ lastCommitAt: any;
10
+ perFile: {
11
+ path: any;
12
+ name: any;
13
+ churn: any;
14
+ authors: any;
15
+ solo: boolean;
16
+ firstSeen: any;
17
+ lastTouched: any;
18
+ complexity: number;
19
+ hotspot: number;
20
+ }[];
21
+ byPath: Record<string, any>;
22
+ soloFiles: number;
23
+ coChanged: any[];
24
+ pathsGone: number;
25
+ };
26
+ export declare function unavailableHistory(reason: any): {
27
+ available: boolean;
28
+ reason: any;
29
+ };