codebase-onboarder 0.6.0 → 1.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 (526) hide show
  1. package/README.md +284 -53
  2. package/bin/build-if-source.js +23 -0
  3. package/bin/onboarder.js +0 -0
  4. package/cli/agent/command.d.ts +71 -0
  5. package/cli/agent/command.js +177 -0
  6. package/cli/agent/command.js.map +1 -0
  7. package/cli/agent/config.d.ts +31 -0
  8. package/cli/agent/config.js +98 -0
  9. package/cli/agent/config.js.map +1 -0
  10. package/cli/agent/contracts.d.ts +77 -0
  11. package/cli/agent/contracts.js +2 -0
  12. package/cli/agent/contracts.js.map +1 -0
  13. package/cli/agent/files.d.ts +19 -0
  14. package/cli/agent/files.js +109 -0
  15. package/cli/agent/files.js.map +1 -0
  16. package/cli/agent/gitSource.d.ts +18 -0
  17. package/cli/agent/gitSource.js +69 -0
  18. package/cli/agent/gitSource.js.map +1 -0
  19. package/cli/agent/github.d.ts +21 -0
  20. package/cli/agent/github.js +94 -0
  21. package/cli/agent/github.js.map +1 -0
  22. package/cli/agent/mcp.d.ts +15 -0
  23. package/cli/agent/mcp.js +78 -0
  24. package/cli/agent/mcp.js.map +1 -0
  25. package/cli/agent/process.d.ts +18 -0
  26. package/cli/agent/process.js +118 -0
  27. package/cli/agent/process.js.map +1 -0
  28. package/cli/agent/protocol.d.ts +3 -0
  29. package/cli/agent/protocol.js +26 -0
  30. package/cli/agent/protocol.js.map +1 -0
  31. package/cli/agent/runner.d.ts +34 -0
  32. package/cli/agent/runner.js +152 -0
  33. package/cli/agent/runner.js.map +1 -0
  34. package/cli/agent/stdio.d.ts +1 -0
  35. package/cli/agent/stdio.js +62 -0
  36. package/cli/agent/stdio.js.map +1 -0
  37. package/cli/agent/tools.d.ts +7 -0
  38. package/cli/agent/tools.js +201 -0
  39. package/cli/agent/tools.js.map +1 -0
  40. package/cli/chat/app.d.ts +16 -0
  41. package/cli/chat/app.js +345 -0
  42. package/cli/chat/app.js.map +1 -0
  43. package/cli/chat/commands.d.ts +11 -0
  44. package/cli/chat/commands.js +120 -0
  45. package/cli/chat/commands.js.map +1 -0
  46. package/cli/chat/composer.d.ts +75 -0
  47. package/cli/chat/composer.js +467 -0
  48. package/cli/chat/composer.js.map +1 -0
  49. package/cli/chat/controller.d.ts +60 -0
  50. package/cli/chat/controller.js +393 -0
  51. package/cli/chat/controller.js.map +1 -0
  52. package/cli/chat/logo.d.ts +3 -0
  53. package/cli/chat/logo.js +14 -0
  54. package/cli/chat/logo.js.map +1 -0
  55. package/cli/chat/models.d.ts +18 -0
  56. package/cli/chat/models.js +88 -0
  57. package/cli/chat/models.js.map +1 -0
  58. package/cli/chat/profile.d.ts +5 -0
  59. package/cli/chat/profile.js +98 -0
  60. package/cli/chat/profile.js.map +1 -0
  61. package/cli/chat/render.d.ts +40 -0
  62. package/cli/chat/render.js +259 -0
  63. package/cli/chat/render.js.map +1 -0
  64. package/cli/chat/screen.d.ts +26 -0
  65. package/cli/chat/screen.js +117 -0
  66. package/cli/chat/screen.js.map +1 -0
  67. package/cli/chat/source.d.ts +29 -0
  68. package/cli/chat/source.js +116 -0
  69. package/cli/chat/source.js.map +1 -0
  70. package/cli/chat/store.d.ts +43 -0
  71. package/cli/chat/store.js +94 -0
  72. package/cli/chat/store.js.map +1 -0
  73. package/cli/chat/text.d.ts +4 -0
  74. package/cli/chat/text.js +27 -0
  75. package/cli/chat/text.js.map +1 -0
  76. package/cli/commands.d.ts +26 -0
  77. package/cli/commands.js +836 -811
  78. package/cli/commands.js.map +1 -0
  79. package/cli/explorer/advanced.d.ts +14 -0
  80. package/cli/explorer/advanced.js +321 -329
  81. package/cli/explorer/advanced.js.map +1 -0
  82. package/cli/explorer/app.d.ts +2 -0
  83. package/cli/explorer/app.js +404 -314
  84. package/cli/explorer/app.js.map +1 -0
  85. package/cli/explorer/assistant.d.ts +9 -0
  86. package/cli/explorer/assistant.js +58 -0
  87. package/cli/explorer/assistant.js.map +1 -0
  88. package/cli/explorer/commands.d.ts +17 -0
  89. package/cli/explorer/commands.js +373 -302
  90. package/cli/explorer/commands.js.map +1 -0
  91. package/cli/explorer/featureViews.d.ts +124 -0
  92. package/cli/explorer/featureViews.js +179 -0
  93. package/cli/explorer/featureViews.js.map +1 -0
  94. package/cli/explorer/github.d.ts +21 -0
  95. package/cli/explorer/github.js +42 -44
  96. package/cli/explorer/github.js.map +1 -0
  97. package/cli/explorer/graphs.d.ts +7 -0
  98. package/cli/explorer/graphs.js +90 -95
  99. package/cli/explorer/graphs.js.map +1 -0
  100. package/cli/explorer/picker.d.ts +22 -0
  101. package/cli/explorer/picker.js +150 -0
  102. package/cli/explorer/picker.js.map +1 -0
  103. package/cli/explorer/report.d.ts +85 -0
  104. package/cli/explorer/report.js +60 -0
  105. package/cli/explorer/report.js.map +1 -0
  106. package/cli/explorer/session.d.ts +449 -0
  107. package/cli/explorer/session.js +143 -144
  108. package/cli/explorer/session.js.map +1 -0
  109. package/cli/explorer/views.d.ts +19 -0
  110. package/cli/explorer/views.js +465 -482
  111. package/cli/explorer/views.js.map +1 -0
  112. package/cli/explorer/wrap.d.ts +1 -0
  113. package/cli/explorer/wrap.js +28 -44
  114. package/cli/explorer/wrap.js.map +1 -0
  115. package/cli/main.d.ts +1 -0
  116. package/cli/main.js +251 -164
  117. package/cli/main.js.map +1 -0
  118. package/cli/prompt.d.ts +5 -0
  119. package/cli/prompt.js +84 -80
  120. package/cli/prompt.js.map +1 -0
  121. package/cli/scanOptions.d.ts +2 -0
  122. package/cli/scanOptions.js +11 -0
  123. package/cli/scanOptions.js.map +1 -0
  124. package/cli/ui.d.ts +33 -0
  125. package/cli/ui.js +35 -44
  126. package/cli/ui.js.map +1 -0
  127. package/cli/wizard.d.ts +187 -0
  128. package/cli/wizard.js +304 -284
  129. package/cli/wizard.js.map +1 -0
  130. package/docs/HERMES_RESEARCH.md +51 -0
  131. package/package.json +16 -4
  132. package/public/app.d.ts +1 -0
  133. package/public/app.js +1133 -1011
  134. package/public/app.js.map +1 -0
  135. package/public/assets/onboarder-mark.svg +11 -0
  136. package/public/browser.d.ts +71 -0
  137. package/public/browser.js +2 -0
  138. package/public/browser.js.map +1 -0
  139. package/public/index.html +54 -20
  140. package/public/js/about.d.ts +6 -0
  141. package/public/js/about.js +152 -172
  142. package/public/js/about.js.map +1 -0
  143. package/public/js/aiDraft.d.ts +4 -0
  144. package/public/js/aiDraft.js +166 -125
  145. package/public/js/aiDraft.js.map +1 -0
  146. package/public/js/analysisPanel.d.ts +7 -0
  147. package/public/js/analysisPanel.js +166 -166
  148. package/public/js/analysisPanel.js.map +1 -0
  149. package/public/js/analysisReport.d.ts +38 -0
  150. package/public/js/analysisReport.js +105 -110
  151. package/public/js/analysisReport.js.map +1 -0
  152. package/public/js/api.d.ts +29 -0
  153. package/public/js/api.js +198 -166
  154. package/public/js/api.js.map +1 -0
  155. package/public/js/atlas.d.ts +6 -0
  156. package/public/js/atlas.js +50 -58
  157. package/public/js/atlas.js.map +1 -0
  158. package/public/js/blameView.d.ts +2 -0
  159. package/public/js/blameView.js +36 -37
  160. package/public/js/blameView.js.map +1 -0
  161. package/public/js/codeTab.d.ts +3 -0
  162. package/public/js/codeTab.js +175 -180
  163. package/public/js/codeTab.js.map +1 -0
  164. package/public/js/codeViewer.d.ts +5 -0
  165. package/public/js/codeViewer.js +162 -150
  166. package/public/js/codeViewer.js.map +1 -0
  167. package/public/js/components/FileChip.d.ts +9 -0
  168. package/public/js/components/FileChip.js +45 -49
  169. package/public/js/components/FileChip.js.map +1 -0
  170. package/public/js/components/MetricSparkline.d.ts +7 -0
  171. package/public/js/components/MetricSparkline.js +35 -44
  172. package/public/js/components/MetricSparkline.js.map +1 -0
  173. package/public/js/components/RiskBadge.d.ts +9 -0
  174. package/public/js/components/RiskBadge.js +55 -63
  175. package/public/js/components/RiskBadge.js.map +1 -0
  176. package/public/js/deepAnalysisView.d.ts +99 -0
  177. package/public/js/deepAnalysisView.js +282 -302
  178. package/public/js/deepAnalysisView.js.map +1 -0
  179. package/public/js/diagramPane.d.ts +9 -0
  180. package/public/js/diagramPane.js +138 -135
  181. package/public/js/diagramPane.js.map +1 -0
  182. package/public/js/diffView.d.ts +6 -0
  183. package/public/js/diffView.js +222 -209
  184. package/public/js/diffView.js.map +1 -0
  185. package/public/js/docsView.d.ts +2 -0
  186. package/public/js/docsView.js +441 -442
  187. package/public/js/docsView.js.map +1 -0
  188. package/public/js/dom.d.ts +197 -0
  189. package/public/js/dom.js +5 -0
  190. package/public/js/dom.js.map +1 -0
  191. package/public/js/fileSourceBrowser.d.ts +5 -0
  192. package/public/js/fileSourceBrowser.js +33 -41
  193. package/public/js/fileSourceBrowser.js.map +1 -0
  194. package/public/js/flameGraph.d.ts +5 -0
  195. package/public/js/flameGraph.js +62 -72
  196. package/public/js/flameGraph.js.map +1 -0
  197. package/public/js/forceGraph.d.ts +10 -0
  198. package/public/js/forceGraph.js +581 -556
  199. package/public/js/forceGraph.js.map +1 -0
  200. package/public/js/heatmap.d.ts +4 -0
  201. package/public/js/heatmap.js +142 -164
  202. package/public/js/heatmap.js.map +1 -0
  203. package/public/js/highlight.d.ts +2 -0
  204. package/public/js/highlight.js +116 -107
  205. package/public/js/highlight.js.map +1 -0
  206. package/public/js/html.d.ts +2 -0
  207. package/public/js/html.js +14 -44
  208. package/public/js/html.js.map +1 -0
  209. package/public/js/insightsView.d.ts +5 -0
  210. package/public/js/insightsView.js +93 -111
  211. package/public/js/insightsView.js.map +1 -0
  212. package/public/js/inspector.d.ts +37 -0
  213. package/public/js/inspector.js +416 -445
  214. package/public/js/inspector.js.map +1 -0
  215. package/public/js/llm.d.ts +115 -0
  216. package/public/js/llm.js +246 -278
  217. package/public/js/llm.js.map +1 -0
  218. package/public/js/mapView.d.ts +3 -0
  219. package/public/js/mapView.js +121 -120
  220. package/public/js/mapView.js.map +1 -0
  221. package/public/js/markdown.d.ts +3 -0
  222. package/public/js/markdown.js +84 -91
  223. package/public/js/markdown.js.map +1 -0
  224. package/public/js/mindmap.d.ts +32 -0
  225. package/public/js/mindmap.js +244 -259
  226. package/public/js/mindmap.js.map +1 -0
  227. package/public/js/mobilePanels.d.ts +5 -0
  228. package/public/js/mobilePanels.js +50 -0
  229. package/public/js/mobilePanels.js.map +1 -0
  230. package/public/js/repoFiles.d.ts +12 -0
  231. package/public/js/repoFiles.js +29 -28
  232. package/public/js/repoFiles.js.map +1 -0
  233. package/public/js/reviewView.d.ts +28 -0
  234. package/public/js/reviewView.js +256 -0
  235. package/public/js/reviewView.js.map +1 -0
  236. package/public/js/sbomView.d.ts +3 -0
  237. package/public/js/sbomView.js +59 -67
  238. package/public/js/sbomView.js.map +1 -0
  239. package/public/js/scanCache.d.ts +16 -0
  240. package/public/js/scanCache.js +67 -65
  241. package/public/js/scanCache.js.map +1 -0
  242. package/public/js/search.d.ts +7 -0
  243. package/public/js/search.js +868 -800
  244. package/public/js/search.js.map +1 -0
  245. package/public/js/searchLocal.d.ts +42 -0
  246. package/public/js/searchLocal.js +87 -0
  247. package/public/js/searchLocal.js.map +1 -0
  248. package/public/js/serverSettings.d.ts +5 -0
  249. package/public/js/serverSettings.js +153 -164
  250. package/public/js/serverSettings.js.map +1 -0
  251. package/public/js/state.d.ts +798 -0
  252. package/public/js/state.js +114 -122
  253. package/public/js/state.js.map +1 -0
  254. package/public/js/tour.d.ts +6 -0
  255. package/public/js/tour.js +5 -7
  256. package/public/js/tour.js.map +1 -0
  257. package/public/js/transitions.d.ts +2 -0
  258. package/public/js/transitions.js +9 -10
  259. package/public/js/transitions.js.map +1 -0
  260. package/public/js/tree.d.ts +12 -0
  261. package/public/js/tree.js +157 -154
  262. package/public/js/tree.js.map +1 -0
  263. package/public/js/workflowsView.d.ts +3 -0
  264. package/public/js/workflowsView.js +15 -22
  265. package/public/js/workflowsView.js.map +1 -0
  266. package/public/search.css +495 -0
  267. package/public/styles.css +188 -346
  268. package/public/workbench.css +166 -0
  269. package/server/apiAuth.d.ts +3 -0
  270. package/server/apiAuth.js +18 -20
  271. package/server/apiAuth.js.map +1 -0
  272. package/server/apiDiff.d.ts +2 -0
  273. package/server/apiDiff.js +20 -18
  274. package/server/apiDiff.js.map +1 -0
  275. package/server/apiDocs.d.ts +2 -0
  276. package/server/apiDocs.js +38 -40
  277. package/server/apiDocs.js.map +1 -0
  278. package/server/apiFile.d.ts +1 -0
  279. package/server/apiFile.js +14 -17
  280. package/server/apiFile.js.map +1 -0
  281. package/server/apiGitBlame.d.ts +2 -0
  282. package/server/apiGitBlame.js +50 -51
  283. package/server/apiGitBlame.js.map +1 -0
  284. package/server/apiMcp.d.ts +4 -0
  285. package/server/apiMcp.js +64 -66
  286. package/server/apiMcp.js.map +1 -0
  287. package/server/apiReview.d.ts +2 -0
  288. package/server/apiReview.js +45 -0
  289. package/server/apiReview.js.map +1 -0
  290. package/server/apiScan.d.ts +5 -0
  291. package/server/apiScan.js +90 -71
  292. package/server/apiScan.js.map +1 -0
  293. package/server/apiSearch.d.ts +33 -0
  294. package/server/apiSearch.js +184 -200
  295. package/server/apiSearch.js.map +1 -0
  296. package/server/apiSettings.d.ts +4 -0
  297. package/server/apiSettings.js +84 -85
  298. package/server/apiSettings.js.map +1 -0
  299. package/server/apiTools.d.ts +3 -0
  300. package/server/apiTools.js +55 -56
  301. package/server/apiTools.js.map +1 -0
  302. package/server/auth.d.ts +5 -0
  303. package/server/auth.js +54 -51
  304. package/server/auth.js.map +1 -0
  305. package/server/config.d.ts +42 -0
  306. package/server/config.js +189 -194
  307. package/server/config.js.map +1 -0
  308. package/server/daemon.d.ts +12 -0
  309. package/server/daemon.js +124 -114
  310. package/server/daemon.js.map +1 -0
  311. package/server/fileSourceNode.d.ts +2 -0
  312. package/server/fileSourceNode.js +34 -36
  313. package/server/fileSourceNode.js.map +1 -0
  314. package/server/gitClone.d.ts +9 -0
  315. package/server/gitClone.js +59 -61
  316. package/server/gitClone.js.map +1 -0
  317. package/server/gitDiff.d.ts +36 -0
  318. package/server/gitDiff.js +271 -169
  319. package/server/gitDiff.js.map +1 -0
  320. package/server/gitHistory.d.ts +12 -0
  321. package/server/gitHistory.js +80 -80
  322. package/server/gitHistory.js.map +1 -0
  323. package/server/gitRemote.d.ts +12 -0
  324. package/server/gitRemote.js +37 -38
  325. package/server/gitRemote.js.map +1 -0
  326. package/server/hermesChat.d.ts +13 -0
  327. package/server/hermesChat.js +145 -0
  328. package/server/hermesChat.js.map +1 -0
  329. package/server/htmlText.d.ts +4 -0
  330. package/server/htmlText.js +16 -23
  331. package/server/htmlText.js.map +1 -0
  332. package/server/http.d.ts +6 -0
  333. package/server/http.js +27 -34
  334. package/server/http.js.map +1 -0
  335. package/server/httpGuards.d.ts +2 -0
  336. package/server/httpGuards.js +47 -43
  337. package/server/httpGuards.js.map +1 -0
  338. package/server/https.d.ts +34 -0
  339. package/server/https.js +121 -111
  340. package/server/https.js.map +1 -0
  341. package/server/index.d.ts +40 -0
  342. package/server/index.js +139 -147
  343. package/server/index.js.map +1 -0
  344. package/server/layout.d.ts +26 -0
  345. package/server/layout.js +59 -64
  346. package/server/layout.js.map +1 -0
  347. package/server/llmProxy.d.ts +3 -0
  348. package/server/llmProxy.js +137 -135
  349. package/server/llmProxy.js.map +1 -0
  350. package/server/logger.d.ts +38 -0
  351. package/server/logger.js +198 -211
  352. package/server/logger.js.map +1 -0
  353. package/server/mcp/analysis.d.ts +29 -0
  354. package/server/mcp/analysis.js +99 -120
  355. package/server/mcp/analysis.js.map +1 -0
  356. package/server/mcp/http.d.ts +9 -0
  357. package/server/mcp/http.js +128 -137
  358. package/server/mcp/http.js.map +1 -0
  359. package/server/mcp/runner.d.ts +68 -0
  360. package/server/mcp/runner.js +208 -218
  361. package/server/mcp/runner.js.map +1 -0
  362. package/server/mcp/server.d.ts +29 -0
  363. package/server/mcp/server.js +167 -180
  364. package/server/mcp/server.js.map +1 -0
  365. package/server/mcp/standalone.d.ts +1 -0
  366. package/server/mcp/standalone.js +8 -10
  367. package/server/mcp/standalone.js.map +1 -0
  368. package/server/mcp/tools.d.ts +2020 -0
  369. package/server/mcp/tools.js +523 -574
  370. package/server/mcp/tools.js.map +1 -0
  371. package/server/paths.d.ts +3 -0
  372. package/server/paths.js +17 -15
  373. package/server/paths.js.map +1 -0
  374. package/server/pidfile.d.ts +9 -0
  375. package/server/pidfile.js +43 -45
  376. package/server/pidfile.js.map +1 -0
  377. package/server/review.d.ts +5 -0
  378. package/server/review.js +35 -0
  379. package/server/review.js.map +1 -0
  380. package/server/router.d.ts +33 -0
  381. package/server/router.js +195 -197
  382. package/server/router.js.map +1 -0
  383. package/server/scanRequest.d.ts +3 -0
  384. package/server/scanRequest.js +36 -0
  385. package/server/scanRequest.js.map +1 -0
  386. package/server/searchIndex.d.ts +17 -0
  387. package/server/searchIndex.js +83 -80
  388. package/server/searchIndex.js.map +1 -0
  389. package/server/sessions.d.ts +14 -0
  390. package/server/sessions.js +62 -70
  391. package/server/sessions.js.map +1 -0
  392. package/server/startup.d.ts +118 -0
  393. package/server/startup.js +143 -148
  394. package/server/startup.js.map +1 -0
  395. package/server/static.d.ts +6 -0
  396. package/server/static.js +28 -31
  397. package/server/static.js.map +1 -0
  398. package/server/tools/install.d.ts +4 -0
  399. package/server/tools/install.js +176 -185
  400. package/server/tools/install.js.map +1 -0
  401. package/server/tools/parse.d.ts +8 -0
  402. package/server/tools/parse.js +112 -114
  403. package/server/tools/parse.js.map +1 -0
  404. package/server/tools/platform.d.ts +9 -0
  405. package/server/tools/platform.js +49 -47
  406. package/server/tools/platform.js.map +1 -0
  407. package/server/tools/registry.d.ts +137 -0
  408. package/server/tools/registry.js +173 -172
  409. package/server/tools/registry.js.map +1 -0
  410. package/server/tools/scan.d.ts +34 -0
  411. package/server/tools/scan.js +89 -98
  412. package/server/tools/scan.js.map +1 -0
  413. package/server/tools.d.ts +34 -0
  414. package/server/tools.js +94 -107
  415. package/server/tools.js.map +1 -0
  416. package/server/tunnel.d.ts +29 -0
  417. package/server/tunnel.js +61 -66
  418. package/server/tunnel.js.map +1 -0
  419. package/shared/analyzer/docs.d.ts +16 -0
  420. package/shared/analyzer/docs.js +99 -93
  421. package/shared/analyzer/docs.js.map +1 -0
  422. package/shared/analyzer/explainLocal.d.ts +4 -0
  423. package/shared/analyzer/explainLocal.js +122 -142
  424. package/shared/analyzer/explainLocal.js.map +1 -0
  425. package/shared/analyzer/github.d.ts +37 -0
  426. package/shared/analyzer/github.js +41 -43
  427. package/shared/analyzer/github.js.map +1 -0
  428. package/shared/analyzer/graph.d.ts +41 -0
  429. package/shared/analyzer/graph.js +393 -400
  430. package/shared/analyzer/graph.js.map +1 -0
  431. package/shared/analyzer/health.d.ts +33 -0
  432. package/shared/analyzer/health.js +197 -193
  433. package/shared/analyzer/health.js.map +1 -0
  434. package/shared/analyzer/history.d.ts +29 -0
  435. package/shared/analyzer/history.js +110 -111
  436. package/shared/analyzer/history.js.map +1 -0
  437. package/shared/analyzer/jsonConfig.d.ts +2 -0
  438. package/shared/analyzer/jsonConfig.js +61 -0
  439. package/shared/analyzer/jsonConfig.js.map +1 -0
  440. package/shared/analyzer/languages/csharp.d.ts +26 -0
  441. package/shared/analyzer/languages/csharp.js +83 -88
  442. package/shared/analyzer/languages/csharp.js.map +1 -0
  443. package/shared/analyzer/languages/generic.d.ts +23 -0
  444. package/shared/analyzer/languages/generic.js +94 -105
  445. package/shared/analyzer/languages/generic.js.map +1 -0
  446. package/shared/analyzer/languages/go.d.ts +24 -0
  447. package/shared/analyzer/languages/go.js +45 -54
  448. package/shared/analyzer/languages/go.js.map +1 -0
  449. package/shared/analyzer/languages/index.d.ts +6 -0
  450. package/shared/analyzer/languages/index.js +19 -20
  451. package/shared/analyzer/languages/index.js.map +1 -0
  452. package/shared/analyzer/languages/java.d.ts +20 -0
  453. package/shared/analyzer/languages/java.js +73 -78
  454. package/shared/analyzer/languages/java.js.map +1 -0
  455. package/shared/analyzer/languages/javascript.d.ts +12 -0
  456. package/shared/analyzer/languages/javascript.js +258 -209
  457. package/shared/analyzer/languages/javascript.js.map +1 -0
  458. package/shared/analyzer/languages/python.d.ts +23 -0
  459. package/shared/analyzer/languages/python.js +92 -100
  460. package/shared/analyzer/languages/python.js.map +1 -0
  461. package/shared/analyzer/languages/rust.d.ts +17 -0
  462. package/shared/analyzer/languages/rust.js +96 -98
  463. package/shared/analyzer/languages/rust.js.map +1 -0
  464. package/shared/analyzer/languages/typescript.d.ts +11 -0
  465. package/shared/analyzer/languages/typescript.js +117 -116
  466. package/shared/analyzer/languages/typescript.js.map +1 -0
  467. package/shared/analyzer/licenses.d.ts +18 -0
  468. package/shared/analyzer/licenses.js +130 -133
  469. package/shared/analyzer/licenses.js.map +1 -0
  470. package/shared/analyzer/metrics.d.ts +20 -0
  471. package/shared/analyzer/metrics.js +112 -104
  472. package/shared/analyzer/metrics.js.map +1 -0
  473. package/shared/analyzer/pathUtil.d.ts +10 -0
  474. package/shared/analyzer/pathUtil.js +29 -35
  475. package/shared/analyzer/pathUtil.js.map +1 -0
  476. package/shared/analyzer/patterns.d.ts +11 -0
  477. package/shared/analyzer/patterns.js +231 -253
  478. package/shared/analyzer/patterns.js.map +1 -0
  479. package/shared/analyzer/scan.d.ts +62 -0
  480. package/shared/analyzer/scan.js +451 -442
  481. package/shared/analyzer/scan.js.map +1 -0
  482. package/shared/analyzer/scanControl.d.ts +11 -0
  483. package/shared/analyzer/scanControl.js +62 -0
  484. package/shared/analyzer/scanControl.js.map +1 -0
  485. package/shared/analyzer/security.d.ts +18 -0
  486. package/shared/analyzer/security.js +159 -159
  487. package/shared/analyzer/security.js.map +1 -0
  488. package/shared/analyzer/services.d.ts +5 -0
  489. package/shared/analyzer/services.js +141 -138
  490. package/shared/analyzer/services.js.map +1 -0
  491. package/shared/analyzer/stack.d.ts +6 -0
  492. package/shared/analyzer/stack.js +134 -141
  493. package/shared/analyzer/stack.js.map +1 -0
  494. package/shared/analyzer/tour.d.ts +2 -0
  495. package/shared/analyzer/tour.js +45 -53
  496. package/shared/analyzer/tour.js.map +1 -0
  497. package/shared/analyzer/util.d.ts +8 -0
  498. package/shared/analyzer/util.js +130 -76
  499. package/shared/analyzer/util.js.map +1 -0
  500. package/shared/analyzer/workflows.d.ts +8 -0
  501. package/shared/analyzer/workflows.js +139 -134
  502. package/shared/analyzer/workflows.js.map +1 -0
  503. package/shared/contracts.d.ts +250 -0
  504. package/shared/contracts.js +2 -0
  505. package/shared/contracts.js.map +1 -0
  506. package/shared/diagram/aiFacts.d.ts +35 -0
  507. package/shared/diagram/aiFacts.js +102 -105
  508. package/shared/diagram/aiFacts.js.map +1 -0
  509. package/shared/diagram/aiMermaid.d.ts +5 -0
  510. package/shared/diagram/aiMermaid.js +50 -46
  511. package/shared/diagram/aiMermaid.js.map +1 -0
  512. package/shared/diagram/atlas.d.ts +16 -0
  513. package/shared/diagram/atlas.js +51 -60
  514. package/shared/diagram/atlas.js.map +1 -0
  515. package/shared/diagram/mermaid.d.ts +43 -0
  516. package/shared/diagram/mermaid.js +348 -370
  517. package/shared/diagram/mermaid.js.map +1 -0
  518. package/shared/review/contracts.d.ts +95 -0
  519. package/shared/review/contracts.js +2 -0
  520. package/shared/review/contracts.js.map +1 -0
  521. package/shared/review/review.d.ts +10 -0
  522. package/shared/review/review.js +184 -0
  523. package/shared/review/review.js.map +1 -0
  524. package/shared/search/query.d.ts +32 -0
  525. package/shared/search/query.js +395 -388
  526. package/shared/search/query.js.map +1 -0
@@ -5,17 +5,14 @@
5
5
  // honest translation of "a dependency tree" is the one everybody already knows
6
6
  // how to read: an indented tree with arrows. Neither is a worse version of the
7
7
  // web view — they are the terminal's own idiom, drawn from the same numbers.
8
-
9
8
  import { fit, termWidth } from '../ui.js';
10
9
  import { width } from '../../server/layout.js';
11
-
12
10
  // Five ramp steps. Unicode 2591–2588, with an ASCII floor for terminals that
13
11
  // cannot show them. Density reads as "how dark", which survives being printed in
14
12
  // black and white, redirected to a file, or read by someone who cannot tell the
15
13
  // ramp apart — the thing a color-only heatmap cannot promise.
16
14
  const RAMP_UNICODE = [' ', '░', '▒', '▓', '█'];
17
15
  const RAMP_ASCII = ['.', ':', '+', '*', '#'];
18
-
19
16
  // A row that is `marker + value + tail`, where the tail is the first thing to go
20
17
  // when the terminal is too narrow to hold it.
21
18
  //
@@ -29,7 +26,6 @@ const RAMP_ASCII = ['.', ':', '+', '*', '#'];
29
26
  // characters as if they occupied cells, which is how a "fitted" row still
30
27
  // overflows by the length of the color codes.
31
28
  const MIN_PATH = 8;
32
-
33
29
  // `pad` is the indent *inside* the width budget, not a prefix glued on
34
30
  // afterwards. An earlier version returned `marker + value` and let the caller
35
31
  // prepend `' '`, which is four cells the helper could not see — so every row
@@ -42,18 +38,17 @@ const MIN_PATH = 8;
42
38
  // over-wide marker is still an overflow, so the value is clamped by `w` itself
43
39
  // and the marker is fitted too.
44
40
  export function labelled(marker, value, tail = '', { pad = 0 } = {}) {
45
- const w = termWidth();
46
- const indent = ' '.repeat(Math.max(0, Math.min(pad, Math.max(0, w - 1))));
47
- const markerRoom = Math.max(0, w - width(indent) - 1);
48
- const head = fit(marker, markerRoom);
49
- const lead = width(indent) + width(head);
50
- const withTail = w - lead - width(tail);
51
- if (tail && withTail > MIN_PATH) return indent + head + fit(value, withTail) + tail;
52
- return indent + head + fit(value, Math.max(0, w - lead));
41
+ const w = termWidth();
42
+ const indent = ' '.repeat(Math.max(0, Math.min(pad, Math.max(0, w - 1))));
43
+ const markerRoom = Math.max(0, w - width(indent) - 1);
44
+ const head = fit(marker, markerRoom);
45
+ const lead = width(indent) + width(head);
46
+ const withTail = w - lead - width(tail);
47
+ if (tail && withTail > MIN_PATH)
48
+ return indent + head + fit(value, withTail) + tail;
49
+ return indent + head + fit(value, Math.max(0, w - lead));
53
50
  }
54
-
55
51
  const glyphs = () => (process.platform === 'win32' && !process.env.WT_SESSION ? RAMP_ASCII : RAMP_UNICODE);
56
-
57
52
  // The strongest signal a number gets, as a fraction of the largest, in five
58
53
  // steps. Zero is always the blank cell rather than the faintest mark: "nothing"
59
54
  // and "a little" are different facts, and a heat grid that gives zero a speck of
@@ -63,79 +58,77 @@ const glyphs = () => (process.platform === 'win32' && !process.env.WT_SESSION ?
63
58
  // number 0 for "empty", which then blew up on `.padEnd()` the first time a
64
59
  // genuinely-zero cell was drawn, i.e. only on repos with real structure.
65
60
  function step(value, max) {
66
- const ramp = glyphs();
67
- if (!value || max <= 0) return ramp[0];
68
- const i = Math.min(ramp.length - 1, Math.max(1, Math.ceil((value / max) * (ramp.length - 1))));
69
- return ramp[i];
61
+ const ramp = glyphs();
62
+ if (!value || max <= 0)
63
+ return ramp[0];
64
+ const i = Math.min(ramp.length - 1, Math.max(1, Math.ceil((value / max) * (ramp.length - 1))));
65
+ return ramp[i];
70
66
  }
71
-
72
67
  export { step };
73
-
74
68
  // A horizontal bar, sized as a fraction of the largest value. Exported so every
75
69
  // ranked list draws its bars identically instead of each view re-deriving the
76
70
  // scale and drifting.
77
71
  export function bar(value, max, room) {
78
- if (room <= 0 || !value || max <= 0) return '';
79
- const ramp = glyphs();
80
- const full = Math.max(1, Math.round((value / max) * room));
81
- return ramp[ramp.length - 1].repeat(Math.min(room, full));
72
+ if (room <= 0 || !value || max <= 0)
73
+ return '';
74
+ const ramp = glyphs();
75
+ const full = Math.max(1, Math.round((value / max) * room));
76
+ return ramp[ramp.length - 1].repeat(Math.min(room, full));
82
77
  }
83
-
84
78
  // A vertical bar chart, because some questions are about magnitude across
85
79
  // categories and reading them off a horizontal list is harder than it needs to
86
80
  // be. Columns collapse to a single row when the terminal is too narrow to hold
87
81
  // them, rather than drawing a squeezed, unreadable grid.
88
82
  export function columns(items, { room = 40, rows = 10 } = {}) {
89
- if (!items.length) return [];
90
- const width = Math.max(1, Math.min(items.length, room));
91
- const stepSize = Math.ceil(items.length / width);
92
- const shown = stepSize > 1 ? items.filter((_, i) => i % stepSize === 0).slice(0, width) : items;
93
- const top = Math.max(...shown.map((i) => i.value)) || 1;
94
- const solid = glyphs()[glyphs().length - 1];
95
- const out = [];
96
- for (let level = rows; level >= 1; level--) {
97
- const threshold = (level / rows) * top;
98
- const line = shown.map((i) => (i.value >= threshold ? solid : ' ')).join('');
99
- if (line.trim()) out.push(' ' + line);
100
- }
101
- out.push(' ' + shown.map((i) => String(i.label).slice(0, 1)).join(''));
102
- return out;
83
+ if (!items.length)
84
+ return [];
85
+ const width = Math.max(1, Math.min(items.length, room));
86
+ const stepSize = Math.ceil(items.length / width);
87
+ const shown = stepSize > 1 ? items.filter((_, i) => i % stepSize === 0).slice(0, width) : items;
88
+ const top = Math.max(...shown.map((i) => i.value)) || 1;
89
+ const solid = glyphs()[glyphs().length - 1];
90
+ const out = [];
91
+ for (let level = rows; level >= 1; level--) {
92
+ const threshold = (level / rows) * top;
93
+ const line = shown.map((i) => (i.value >= threshold ? solid : ' ')).join('');
94
+ if (line.trim())
95
+ out.push(' ' + line);
96
+ }
97
+ out.push(' ' + shown.map((i) => String(i.label).slice(0, 1)).join(''));
98
+ return out;
103
99
  }
104
-
105
100
  // The folder-to-folder coupling grid, as a matrix. Row label, then one cell per
106
101
  // folder, heaviest traffic darkest. Columns are addressed by letter so a cell
107
102
  // can be named rather than counted. The diagonal is blank: a folder's traffic
108
103
  // with itself is not coupling, it is just being that folder.
109
104
  export function couplingGrid(repo, { maxFolders = 8, columns: cols } = {}) {
110
- const matrix = repo.coupling;
111
- if (!matrix || !matrix.folders.length) return [];
112
- const folders = matrix.folders.slice(0, maxFolders);
113
- const w = cols || termWidth();
114
- const labelRoom = Math.min(18, Math.max(...folders.map((f) => f.length)) + 1);
115
- const cellRoom = Math.max(1, Math.floor((w - labelRoom - 4) / folders.length));
116
- const cellW = Math.max(1, Math.min(2, cellRoom));
117
-
118
- const head = ' '.repeat(labelRoom) + folders.map((_, i) => String.fromCharCode(65 + i).padEnd(cellW)).join('');
119
- // The rule is sized to the grid but never past the terminal, so a very narrow
120
- // window gets a short rule rather than a wrapped one.
121
- const rule = '─'.repeat(Math.max(1, Math.min(labelRoom + folders.length * cellW, Math.max(1, w - 2))));
122
- const out = [' ' + fit(head, w - 2), ' ' + rule];
123
-
124
- folders.forEach((from, r) => {
125
- let line = fit(from, labelRoom);
126
- folders.forEach((to, c) => {
127
- if (r === c) {
128
- line += ' '.repeat(cellW);
129
- return;
130
- }
131
- const n = matrix.counts.get(from + '->' + to) || 0;
132
- line += step(n, matrix.max).padEnd(cellW);
105
+ const matrix = repo.coupling;
106
+ if (!matrix || !matrix.folders.length)
107
+ return [];
108
+ const folders = matrix.folders.slice(0, maxFolders);
109
+ const w = cols || termWidth();
110
+ const labelRoom = Math.min(18, Math.max(...folders.map((f) => f.length)) + 1);
111
+ const cellRoom = Math.max(1, Math.floor((w - labelRoom - 4) / folders.length));
112
+ const cellW = Math.max(1, Math.min(2, cellRoom));
113
+ const head = ' '.repeat(labelRoom) + folders.map((_, i) => String.fromCharCode(65 + i).padEnd(cellW)).join('');
114
+ // The rule is sized to the grid but never past the terminal, so a very narrow
115
+ // window gets a short rule rather than a wrapped one.
116
+ const rule = '─'.repeat(Math.max(1, Math.min(labelRoom + folders.length * cellW, Math.max(1, w - 2))));
117
+ const out = [' ' + fit(head, w - 2), ' ' + rule];
118
+ folders.forEach((from, r) => {
119
+ let line = fit(from, labelRoom);
120
+ folders.forEach((to, c) => {
121
+ if (r === c) {
122
+ line += ' '.repeat(cellW);
123
+ return;
124
+ }
125
+ const n = matrix.counts.get(from + '->' + to) || 0;
126
+ line += step(n, matrix.max).padEnd(cellW);
127
+ });
128
+ out.push(' ' + fit(line, w - 2));
133
129
  });
134
- out.push(' ' + fit(line, w - 2));
135
- });
136
- return out;
130
+ return out;
137
131
  }
138
-
139
132
  // A dependency tree rooted at a file, drawn as a tree with the one piece of
140
133
  // information that makes a tree readable — which way each edge points. This is
141
134
  // the terminal's answer to the site's force-directed graph: a browser can show
@@ -147,32 +140,34 @@ export function couplingGrid(repo, { maxFolders = 8, columns: cols } = {}) {
147
140
  // a file reached by two different paths is drawn only under the first, which is
148
141
  // the right trade for a bounded tree.
149
142
  export function depTree(repo, rootPath, { depth = 2, direction = 'both', room } = {}) {
150
- const w = room || termWidth();
151
- const out = [];
152
- const seen = new Set([rootPath]);
153
-
154
- const walk = (path, prefix, left, arrow) => {
155
- out.push(fit(prefix + arrow + ' ' + path, w - 2));
156
- if (left <= 0) return;
157
-
158
- const kids = [];
159
- if (direction !== 'up') {
160
- for (const child of repo.facts.importsOf[path] || []) {
161
- if (!seen.has(child)) kids.push({ path: child, arrow: '→' });
162
- }
163
- }
164
- if (direction !== 'down') {
165
- for (const parent of repo.facts.importers[path] || []) {
166
- if (!seen.has(parent)) kids.push({ path: parent, arrow: '←' });
167
- }
168
- }
169
- kids.forEach((k, i) => {
170
- if (seen.has(k.path)) return;
171
- seen.add(k.path);
172
- walk(k.path, prefix + (i === kids.length - 1 ? ' ' : '│ '), left - 1, k.arrow);
173
- });
174
- };
175
-
176
- walk(rootPath, '', depth, '●');
177
- return out;
143
+ const w = room || termWidth();
144
+ const out = [];
145
+ const seen = new Set([rootPath]);
146
+ const walk = (path, prefix, left, arrow) => {
147
+ out.push(fit(prefix + arrow + ' ' + path, w - 2));
148
+ if (left <= 0)
149
+ return;
150
+ const kids = [];
151
+ if (direction !== 'up') {
152
+ for (const child of repo.facts.importsOf[path] || []) {
153
+ if (!seen.has(child))
154
+ kids.push({ path: child, arrow: '→' });
155
+ }
156
+ }
157
+ if (direction !== 'down') {
158
+ for (const parent of repo.facts.importers[path] || []) {
159
+ if (!seen.has(parent))
160
+ kids.push({ path: parent, arrow: '←' });
161
+ }
162
+ }
163
+ kids.forEach((k, i) => {
164
+ if (seen.has(k.path))
165
+ return;
166
+ seen.add(k.path);
167
+ walk(k.path, prefix + (i === kids.length - 1 ? ' ' : '│ '), left - 1, k.arrow);
168
+ });
169
+ };
170
+ walk(rootPath, '', depth, '●');
171
+ return out;
178
172
  }
173
+ //# sourceMappingURL=graphs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graphs.js","sourceRoot":"","sources":["../../src/cli/explorer/graphs.ts"],"names":[],"mappings":"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","sourcesContent":["// Rendering primitives that the terminal can do and a browser cannot afford to.\n//\n// The site's coupling matrix is a canvas heat grid and its mind map is SVG. In a\n// terminal the honest translation of \"a heat grid\" is block characters, and the\n// honest translation of \"a dependency tree\" is the one everybody already knows\n// how to read: an indented tree with arrows. Neither is a worse version of the\n// web view — they are the terminal's own idiom, drawn from the same numbers.\n\nimport { fit, termWidth } from '../ui.js';\nimport { width } from '../../server/layout.js';\n\n// Five ramp steps. Unicode 2591–2588, with an ASCII floor for terminals that\n// cannot show them. Density reads as \"how dark\", which survives being printed in\n// black and white, redirected to a file, or read by someone who cannot tell the\n// ramp apart — the thing a color-only heatmap cannot promise.\nconst RAMP_UNICODE = [' ', '░', '▒', '▓', '█'];\nconst RAMP_ASCII = ['.', ':', '+', '*', '#'];\n\n// A row that is `marker + value + tail`, where the tail is the first thing to go\n// when the terminal is too narrow to hold it.\n//\n// This is the same mistake in five places — health risks, security findings,\n// entry points, symbol rows, and layer notes — and fixing each by hand means the\n// sixth gets it wrong too. The rule in one place: if the tail leaves less than\n// `MIN_PATH` cells for the value, drop the tail and give the value the rest.\n//\n// `marker` may be styled, so its width is measured with `width()` (which strips\n// ANSI) rather than `.length`. Measuring a styled string counts escape-sequence\n// characters as if they occupied cells, which is how a \"fitted\" row still\n// overflows by the length of the color codes.\nconst MIN_PATH = 8;\n\n// `pad` is the indent *inside* the width budget, not a prefix glued on\n// afterwards. An earlier version returned `marker + value` and let the caller\n// prepend `' '`, which is four cells the helper could not see — so every row\n// came out four cells too wide, which is exactly the overflow this exists to\n// prevent. The indent is part of the row now.\n//\n// The value always gets at least one cell and never more than the terminal has\n// left, even when the marker alone is wider than the terminal. That last case is\n// the one a `Math.max(1, …)` floor gets wrong: a floor of 1 plus an\n// over-wide marker is still an overflow, so the value is clamped by `w` itself\n// and the marker is fitted too.\nexport function labelled(marker, value, tail = '', { pad = 0 }: Record<string, any> = {}) {\n const w = termWidth();\n const indent = ' '.repeat(Math.max(0, Math.min(pad, Math.max(0, w - 1))));\n const markerRoom = Math.max(0, w - width(indent) - 1);\n const head = fit(marker, markerRoom);\n const lead = width(indent) + width(head);\n const withTail = w - lead - width(tail);\n if (tail && withTail > MIN_PATH) return indent + head + fit(value, withTail) + tail;\n return indent + head + fit(value, Math.max(0, w - lead));\n}\n\nconst glyphs = () => (process.platform === 'win32' && !process.env.WT_SESSION ? RAMP_ASCII : RAMP_UNICODE);\n\n// The strongest signal a number gets, as a fraction of the largest, in five\n// steps. Zero is always the blank cell rather than the faintest mark: \"nothing\"\n// and \"a little\" are different facts, and a heat grid that gives zero a speck of\n// ink makes every map look busier than it is.\n//\n// Returns the *character*, always a string — an early version returned the\n// number 0 for \"empty\", which then blew up on `.padEnd()` the first time a\n// genuinely-zero cell was drawn, i.e. only on repos with real structure.\nfunction step(value, max) {\n const ramp = glyphs();\n if (!value || max <= 0) return ramp[0];\n const i = Math.min(ramp.length - 1, Math.max(1, Math.ceil((value / max) * (ramp.length - 1))));\n return ramp[i];\n}\n\nexport { step };\n\n// A horizontal bar, sized as a fraction of the largest value. Exported so every\n// ranked list draws its bars identically instead of each view re-deriving the\n// scale and drifting.\nexport function bar(value, max, room) {\n if (room <= 0 || !value || max <= 0) return '';\n const ramp = glyphs();\n const full = Math.max(1, Math.round((value / max) * room));\n return ramp[ramp.length - 1].repeat(Math.min(room, full));\n}\n\n// A vertical bar chart, because some questions are about magnitude across\n// categories and reading them off a horizontal list is harder than it needs to\n// be. Columns collapse to a single row when the terminal is too narrow to hold\n// them, rather than drawing a squeezed, unreadable grid.\nexport function columns(items, { room = 40, rows = 10 }: Record<string, any> = {}) {\n if (!items.length) return [];\n const width = Math.max(1, Math.min(items.length, room));\n const stepSize = Math.ceil(items.length / width);\n const shown = stepSize > 1 ? items.filter((_, i) => i % stepSize === 0).slice(0, width) : items;\n const top = Math.max(...shown.map((i) => i.value)) || 1;\n const solid = glyphs()[glyphs().length - 1];\n const out = [];\n for (let level = rows; level >= 1; level--) {\n const threshold = (level / rows) * top;\n const line = shown.map((i) => (i.value >= threshold ? solid : ' ')).join('');\n if (line.trim()) out.push(' ' + line);\n }\n out.push(' ' + shown.map((i) => String(i.label).slice(0, 1)).join(''));\n return out;\n}\n\n// The folder-to-folder coupling grid, as a matrix. Row label, then one cell per\n// folder, heaviest traffic darkest. Columns are addressed by letter so a cell\n// can be named rather than counted. The diagonal is blank: a folder's traffic\n// with itself is not coupling, it is just being that folder.\nexport function couplingGrid(repo, { maxFolders = 8, columns: cols }: Record<string, any> = {}) {\n const matrix = repo.coupling;\n if (!matrix || !matrix.folders.length) return [];\n const folders = matrix.folders.slice(0, maxFolders);\n const w = cols || termWidth();\n const labelRoom = Math.min(18, Math.max(...folders.map((f) => f.length)) + 1);\n const cellRoom = Math.max(1, Math.floor((w - labelRoom - 4) / folders.length));\n const cellW = Math.max(1, Math.min(2, cellRoom));\n\n const head = ' '.repeat(labelRoom) + folders.map((_, i) => String.fromCharCode(65 + i).padEnd(cellW)).join('');\n // The rule is sized to the grid but never past the terminal, so a very narrow\n // window gets a short rule rather than a wrapped one.\n const rule = '─'.repeat(Math.max(1, Math.min(labelRoom + folders.length * cellW, Math.max(1, w - 2))));\n const out = [' ' + fit(head, w - 2), ' ' + rule];\n\n folders.forEach((from, r) => {\n let line = fit(from, labelRoom);\n folders.forEach((to, c) => {\n if (r === c) {\n line += ' '.repeat(cellW);\n return;\n }\n const n = matrix.counts.get(from + '->' + to) || 0;\n line += step(n, matrix.max).padEnd(cellW);\n });\n out.push(' ' + fit(line, w - 2));\n });\n return out;\n}\n\n// A dependency tree rooted at a file, drawn as a tree with the one piece of\n// information that makes a tree readable — which way each edge points. This is\n// the terminal's answer to the site's force-directed graph: a browser can show\n// every edge at once, a terminal cannot, so it shows the part that answers \"what\n// breaks if I break this\".\n//\n// The `seen` set makes the walk terminate on a cyclic graph — without it, a\n// two-file import cycle would recurse until the stack gave out. The cost is that\n// a file reached by two different paths is drawn only under the first, which is\n// the right trade for a bounded tree.\nexport function depTree(repo, rootPath, { depth = 2, direction = 'both', room }: Record<string, any> = {}) {\n const w = room || termWidth();\n const out = [];\n const seen = new Set([rootPath]);\n\n const walk = (path, prefix, left, arrow) => {\n out.push(fit(prefix + arrow + ' ' + path, w - 2));\n if (left <= 0) return;\n\n const kids = [];\n if (direction !== 'up') {\n for (const child of repo.facts.importsOf[path] || []) {\n if (!seen.has(child)) kids.push({ path: child, arrow: '→' });\n }\n }\n if (direction !== 'down') {\n for (const parent of repo.facts.importers[path] || []) {\n if (!seen.has(parent)) kids.push({ path: parent, arrow: '←' });\n }\n }\n kids.forEach((k, i) => {\n if (seen.has(k.path)) return;\n seen.add(k.path);\n walk(k.path, prefix + (i === kids.length - 1 ? ' ' : '│ '), left - 1, k.arrow);\n });\n };\n\n walk(rootPath, '', depth, '●');\n return out;\n}\n"]}
@@ -0,0 +1,22 @@
1
+ export type PickerResult = {
2
+ done: true;
3
+ target: string | null;
4
+ message: string;
5
+ } | {
6
+ done: false;
7
+ message: string;
8
+ };
9
+ /** A prompt-driven folder picker that can share an existing readline session. */
10
+ export declare class SourcePicker {
11
+ private mode;
12
+ private location;
13
+ private page;
14
+ private directories;
15
+ private readonly pageSize;
16
+ constructor(start?: string);
17
+ get prompt(): string;
18
+ view(): Promise<string>;
19
+ choose(input: string): Promise<PickerResult>;
20
+ private browseView;
21
+ private validateTarget;
22
+ }
@@ -0,0 +1,150 @@
1
+ import { promises as fs } from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ function render(lines) {
5
+ const width = Math.max(1, Number(process.env.COLUMNS) || process.stdout.columns || 80);
6
+ return lines.map((line) => {
7
+ const chars = [...line];
8
+ if (chars.length <= width)
9
+ return line;
10
+ const lead = Math.ceil((width - 1) * 0.4);
11
+ return chars.slice(0, lead).join('') + '…' + chars.slice(chars.length - (width - 1 - lead)).join('');
12
+ }).join('\n');
13
+ }
14
+ /** A prompt-driven folder picker that can share an existing readline session. */
15
+ export class SourcePicker {
16
+ mode = 'menu';
17
+ location;
18
+ page = 0;
19
+ directories = [];
20
+ pageSize = 12;
21
+ constructor(start = process.cwd()) {
22
+ this.location = path.resolve(start);
23
+ }
24
+ get prompt() { return ' choose > '; }
25
+ async view() {
26
+ if (this.mode === 'menu')
27
+ return render([
28
+ '',
29
+ ' SELECT A REPOSITORY',
30
+ ` 1 Use current folder ${this.location}`,
31
+ ' 2 Browse folders on this device',
32
+ ' 3 Enter a folder path or Git URL',
33
+ ' q Cancel',
34
+ '',
35
+ ]);
36
+ if (this.mode === 'entry')
37
+ return render([
38
+ '',
39
+ ' Enter an existing folder path or a Git URL.',
40
+ ' Examples: ~/Projects/my-app · https://github.com/org/repo',
41
+ ' Type `back` to return to the menu.',
42
+ '',
43
+ ]);
44
+ return this.browseView();
45
+ }
46
+ async choose(input) {
47
+ const value = input.trim();
48
+ if (value === 'q' || value === 'quit' || value === 'cancel') {
49
+ return { done: true, target: null, message: ' Selection cancelled.' };
50
+ }
51
+ if (this.mode === 'menu') {
52
+ if (value === '1' || value === '')
53
+ return { done: true, target: this.location, message: '' };
54
+ if (value === '2') {
55
+ this.mode = 'browse';
56
+ this.page = 0;
57
+ return { done: false, message: await this.view() };
58
+ }
59
+ if (value === '3') {
60
+ this.mode = 'entry';
61
+ return { done: false, message: await this.view() };
62
+ }
63
+ // A pasted path or URL should work immediately, without selecting 3 first.
64
+ return this.validateTarget(value);
65
+ }
66
+ if (this.mode === 'entry') {
67
+ if (value === 'back' || !value) {
68
+ this.mode = 'menu';
69
+ return { done: false, message: await this.view() };
70
+ }
71
+ return this.validateTarget(value);
72
+ }
73
+ if (value === 'back') {
74
+ this.mode = 'menu';
75
+ return { done: false, message: await this.view() };
76
+ }
77
+ if (value === 'home') {
78
+ this.location = os.homedir();
79
+ this.page = 0;
80
+ return { done: false, message: await this.view() };
81
+ }
82
+ if (value === '..') {
83
+ this.location = path.dirname(this.location);
84
+ this.page = 0;
85
+ return { done: false, message: await this.view() };
86
+ }
87
+ if (value === 'use' || value === '.')
88
+ return { done: true, target: this.location, message: '' };
89
+ if (value === 'n' && (this.page + 1) * this.pageSize < this.directories.length) {
90
+ this.page++;
91
+ return { done: false, message: await this.view() };
92
+ }
93
+ if (value === 'p' && this.page > 0) {
94
+ this.page--;
95
+ return { done: false, message: await this.view() };
96
+ }
97
+ const number = Number(value);
98
+ if (Number.isInteger(number) && number >= 1 && number <= this.pageSize) {
99
+ const selected = this.directories[this.page * this.pageSize + number - 1];
100
+ if (selected) {
101
+ this.location = path.join(this.location, selected);
102
+ this.page = 0;
103
+ return { done: false, message: await this.view() };
104
+ }
105
+ }
106
+ if (value) {
107
+ const result = await this.validateTarget(value);
108
+ if (result.done)
109
+ return result;
110
+ }
111
+ return { done: false, message: ' Choose a listed folder, `use`, `..`, `home`, or paste a path.' };
112
+ }
113
+ async browseView() {
114
+ try {
115
+ const entries = await fs.readdir(this.location, { withFileTypes: true });
116
+ this.directories = entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name)
117
+ .sort((a, b) => a.localeCompare(b));
118
+ }
119
+ catch (error) {
120
+ this.mode = 'menu';
121
+ const message = error instanceof Error ? error.message : String(error);
122
+ return ` Cannot browse ${this.location}: ${message}\n${await this.view()}`;
123
+ }
124
+ const pages = Math.max(1, Math.ceil(this.directories.length / this.pageSize));
125
+ this.page = Math.min(this.page, pages - 1);
126
+ const shown = this.directories.slice(this.page * this.pageSize, (this.page + 1) * this.pageSize);
127
+ return render([
128
+ '',
129
+ ` FOLDERS ${this.location}`,
130
+ ...shown.map((name, index) => ` ${String(index + 1).padStart(2)} ${name}/`),
131
+ ...(shown.length ? [] : [' No subfolders here.']),
132
+ ` Page ${this.page + 1}/${pages} · n/p next/previous`,
133
+ ' use Select this folder .. Parent home Home back Menu',
134
+ '',
135
+ ]);
136
+ }
137
+ async validateTarget(value) {
138
+ if (/^(https?:\/\/|git@|ssh:\/\/)/i.test(value)) {
139
+ return { done: true, target: value, message: '' };
140
+ }
141
+ const expanded = value === '~' ? os.homedir() : value.startsWith('~/')
142
+ ? path.join(os.homedir(), value.slice(2)) : value;
143
+ const target = path.resolve(expanded);
144
+ const stat = await fs.stat(target).catch(() => null);
145
+ if (stat?.isDirectory())
146
+ return { done: true, target, message: '' };
147
+ return { done: false, message: ` No folder found at ${target}. Try another path or back.` };
148
+ }
149
+ }
150
+ //# sourceMappingURL=picker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"picker.js","sourceRoot":"","sources":["../../src/cli/explorer/picker.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as fs } from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\ntype Mode = 'menu' | 'browse' | 'entry';\n\nfunction render(lines: string[]): string {\n const width = Math.max(1, Number(process.env.COLUMNS) || process.stdout.columns || 80);\n return lines.map((line) => {\n const chars = [...line];\n if (chars.length <= width) return line;\n const lead = Math.ceil((width - 1) * 0.4);\n return chars.slice(0, lead).join('') + '…' + chars.slice(chars.length - (width - 1 - lead)).join('');\n }).join('\\n');\n}\n\nexport type PickerResult =\n | { done: true; target: string | null; message: string }\n | { done: false; message: string };\n\n/** A prompt-driven folder picker that can share an existing readline session. */\nexport class SourcePicker {\n private mode: Mode = 'menu';\n private location: string;\n private page = 0;\n private directories: string[] = [];\n private readonly pageSize = 12;\n\n constructor(start = process.cwd()) {\n this.location = path.resolve(start);\n }\n\n get prompt(): string { return ' choose > '; }\n\n async view(): Promise<string> {\n if (this.mode === 'menu') return render([\n '',\n ' SELECT A REPOSITORY',\n ` 1 Use current folder ${this.location}`,\n ' 2 Browse folders on this device',\n ' 3 Enter a folder path or Git URL',\n ' q Cancel',\n '',\n ]);\n if (this.mode === 'entry') return render([\n '',\n ' Enter an existing folder path or a Git URL.',\n ' Examples: ~/Projects/my-app · https://github.com/org/repo',\n ' Type `back` to return to the menu.',\n '',\n ]);\n return this.browseView();\n }\n\n async choose(input: string): Promise<PickerResult> {\n const value = input.trim();\n if (value === 'q' || value === 'quit' || value === 'cancel') {\n return { done: true, target: null, message: ' Selection cancelled.' };\n }\n if (this.mode === 'menu') {\n if (value === '1' || value === '') return { done: true, target: this.location, message: '' };\n if (value === '2') {\n this.mode = 'browse';\n this.page = 0;\n return { done: false, message: await this.view() };\n }\n if (value === '3') {\n this.mode = 'entry';\n return { done: false, message: await this.view() };\n }\n // A pasted path or URL should work immediately, without selecting 3 first.\n return this.validateTarget(value);\n }\n if (this.mode === 'entry') {\n if (value === 'back' || !value) {\n this.mode = 'menu';\n return { done: false, message: await this.view() };\n }\n return this.validateTarget(value);\n }\n if (value === 'back') {\n this.mode = 'menu';\n return { done: false, message: await this.view() };\n }\n if (value === 'home') {\n this.location = os.homedir();\n this.page = 0;\n return { done: false, message: await this.view() };\n }\n if (value === '..') {\n this.location = path.dirname(this.location);\n this.page = 0;\n return { done: false, message: await this.view() };\n }\n if (value === 'use' || value === '.') return { done: true, target: this.location, message: '' };\n if (value === 'n' && (this.page + 1) * this.pageSize < this.directories.length) {\n this.page++;\n return { done: false, message: await this.view() };\n }\n if (value === 'p' && this.page > 0) {\n this.page--;\n return { done: false, message: await this.view() };\n }\n const number = Number(value);\n if (Number.isInteger(number) && number >= 1 && number <= this.pageSize) {\n const selected = this.directories[this.page * this.pageSize + number - 1];\n if (selected) {\n this.location = path.join(this.location, selected);\n this.page = 0;\n return { done: false, message: await this.view() };\n }\n }\n if (value) {\n const result = await this.validateTarget(value);\n if (result.done) return result;\n }\n return { done: false, message: ' Choose a listed folder, `use`, `..`, `home`, or paste a path.' };\n }\n\n private async browseView(): Promise<string> {\n try {\n const entries = await fs.readdir(this.location, { withFileTypes: true });\n this.directories = entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name)\n .sort((a, b) => a.localeCompare(b));\n } catch (error) {\n this.mode = 'menu';\n const message = error instanceof Error ? error.message : String(error);\n return ` Cannot browse ${this.location}: ${message}\\n${await this.view()}`;\n }\n const pages = Math.max(1, Math.ceil(this.directories.length / this.pageSize));\n this.page = Math.min(this.page, pages - 1);\n const shown = this.directories.slice(this.page * this.pageSize, (this.page + 1) * this.pageSize);\n return render([\n '',\n ` FOLDERS ${this.location}`,\n ...shown.map((name, index) => ` ${String(index + 1).padStart(2)} ${name}/`),\n ...(shown.length ? [] : [' No subfolders here.']),\n ` Page ${this.page + 1}/${pages} · n/p next/previous`,\n ' use Select this folder .. Parent home Home back Menu',\n '',\n ]);\n }\n\n private async validateTarget(value: string): Promise<PickerResult> {\n if (/^(https?:\\/\\/|git@|ssh:\\/\\/)/i.test(value)) {\n return { done: true, target: value, message: '' };\n }\n const expanded = value === '~' ? os.homedir() : value.startsWith('~/')\n ? path.join(os.homedir(), value.slice(2)) : value;\n const target = path.resolve(expanded);\n const stat = await fs.stat(target).catch(() => null);\n if (stat?.isDirectory()) return { done: true, target, message: '' };\n return { done: false, message: ` No folder found at ${target}. Try another path or back.` };\n }\n}\n"]}
@@ -0,0 +1,85 @@
1
+ /** A stable, small snapshot for scripts and CI. It contains no source text. */
2
+ export interface RepositoryReport {
3
+ schemaVersion: 1;
4
+ repository: {
5
+ name: string;
6
+ root: string;
7
+ };
8
+ scan: {
9
+ parsedFiles: number;
10
+ skipped: number;
11
+ partial: boolean;
12
+ imports: {
13
+ total: number;
14
+ internal: number;
15
+ external: number;
16
+ unresolved: number;
17
+ confidence: number;
18
+ };
19
+ };
20
+ architecture: {
21
+ entryPoints: string[];
22
+ cycles: number;
23
+ topHubs: Array<{
24
+ path: string;
25
+ importedBy: number;
26
+ }>;
27
+ };
28
+ health: {
29
+ grade: string;
30
+ score: number;
31
+ riskiestFiles: Array<{
32
+ path: string;
33
+ risk: number;
34
+ }>;
35
+ };
36
+ security: {
37
+ grade: string;
38
+ findings: number;
39
+ };
40
+ testReachability: {
41
+ reachable: number;
42
+ sourceFiles: number;
43
+ percent: number;
44
+ };
45
+ }
46
+ interface RepositoryInput {
47
+ name: string;
48
+ root: string;
49
+ scan: {
50
+ stats: {
51
+ filesParsed: number;
52
+ skipped: number;
53
+ truncated: unknown;
54
+ imports: RepositoryReport['scan']['imports'];
55
+ };
56
+ };
57
+ facts: {
58
+ entries: string[];
59
+ cycles: unknown[];
60
+ hubs: Array<{
61
+ path: string;
62
+ fanIn: number;
63
+ }>;
64
+ testCoverage: {
65
+ testedCount: number;
66
+ totalNonTest: number;
67
+ ratio: number;
68
+ };
69
+ };
70
+ health: {
71
+ grade: string;
72
+ score: number;
73
+ perFile: Array<{
74
+ path: string;
75
+ risk: number;
76
+ }>;
77
+ };
78
+ security: {
79
+ grade: string;
80
+ total: number;
81
+ };
82
+ }
83
+ export declare function createReport(repo: RepositoryInput): RepositoryReport;
84
+ export declare function formatReport(report: RepositoryReport): string;
85
+ export {};
@@ -0,0 +1,60 @@
1
+ export function createReport(repo) {
2
+ const stats = repo.scan.stats;
3
+ return {
4
+ schemaVersion: 1,
5
+ repository: { name: repo.name, root: repo.root },
6
+ scan: {
7
+ parsedFiles: stats.filesParsed,
8
+ skipped: stats.skipped,
9
+ partial: Boolean(stats.truncated),
10
+ imports: {
11
+ total: stats.imports.total,
12
+ internal: stats.imports.internal,
13
+ external: stats.imports.external,
14
+ unresolved: stats.imports.unresolved,
15
+ confidence: stats.imports.confidence,
16
+ },
17
+ },
18
+ architecture: {
19
+ entryPoints: repo.facts.entries,
20
+ cycles: repo.facts.cycles.length,
21
+ topHubs: repo.facts.hubs.slice(0, 5).map((hub) => ({ path: hub.path, importedBy: hub.fanIn })),
22
+ },
23
+ health: {
24
+ grade: repo.health.grade,
25
+ score: repo.health.score,
26
+ riskiestFiles: repo.health.perFile.slice(0, 5).map(({ path, risk }) => ({ path, risk })),
27
+ },
28
+ security: { grade: repo.security.grade, findings: repo.security.total },
29
+ testReachability: {
30
+ reachable: repo.facts.testCoverage.testedCount,
31
+ sourceFiles: repo.facts.testCoverage.totalNonTest,
32
+ percent: repo.facts.testCoverage.ratio,
33
+ },
34
+ };
35
+ }
36
+ export function formatReport(report) {
37
+ const lines = [
38
+ `${report.repository.name} — codebase report`,
39
+ report.repository.root,
40
+ '',
41
+ `Files ${report.scan.parsedFiles} parsed${report.scan.partial ? ' (partial scan)' : ''}, ${report.scan.skipped} skipped`,
42
+ `Imports ${report.scan.imports.internal} internal, ${report.scan.imports.external} external, ${report.scan.imports.unresolved} unresolved (${report.scan.imports.confidence}% placed)`,
43
+ `Architecture ${report.architecture.entryPoints.length} entry points, ${report.architecture.cycles} cycles`,
44
+ `Health ${report.health.grade} (${report.health.score}/100)`,
45
+ `Security ${report.security.grade} (${report.security.findings} heuristic findings)`,
46
+ `Test reachability ${report.testReachability.reachable}/${report.testReachability.sourceFiles} source files (${report.testReachability.percent}%)`,
47
+ ];
48
+ if (report.architecture.topHubs.length) {
49
+ lines.push('', 'Most imported files');
50
+ for (const hub of report.architecture.topHubs)
51
+ lines.push(` ${hub.path} (${hub.importedBy} importers)`);
52
+ }
53
+ if (report.health.riskiestFiles.length) {
54
+ lines.push('', 'Highest risk files');
55
+ for (const file of report.health.riskiestFiles)
56
+ lines.push(` ${file.path} (risk ${file.risk})`);
57
+ }
58
+ return lines.join('\n');
59
+ }
60
+ //# sourceMappingURL=report.js.map