codebase-onboarder 0.6.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.
- package/README.md +174 -46
- package/bin/build-if-source.js +23 -0
- package/cli/commands.d.ts +26 -0
- package/cli/commands.js +836 -811
- package/cli/commands.js.map +1 -0
- package/cli/explorer/advanced.d.ts +14 -0
- package/cli/explorer/advanced.js +321 -329
- package/cli/explorer/advanced.js.map +1 -0
- package/cli/explorer/app.d.ts +1 -0
- package/cli/explorer/app.js +384 -313
- package/cli/explorer/app.js.map +1 -0
- package/cli/explorer/assistant.d.ts +9 -0
- package/cli/explorer/assistant.js +58 -0
- package/cli/explorer/assistant.js.map +1 -0
- package/cli/explorer/commands.d.ts +17 -0
- package/cli/explorer/commands.js +368 -302
- package/cli/explorer/commands.js.map +1 -0
- package/cli/explorer/featureViews.d.ts +124 -0
- package/cli/explorer/featureViews.js +179 -0
- package/cli/explorer/featureViews.js.map +1 -0
- package/cli/explorer/github.d.ts +21 -0
- package/cli/explorer/github.js +42 -44
- package/cli/explorer/github.js.map +1 -0
- package/cli/explorer/graphs.d.ts +7 -0
- package/cli/explorer/graphs.js +90 -95
- package/cli/explorer/graphs.js.map +1 -0
- package/cli/explorer/picker.d.ts +22 -0
- package/cli/explorer/picker.js +150 -0
- package/cli/explorer/picker.js.map +1 -0
- package/cli/explorer/report.d.ts +85 -0
- package/cli/explorer/report.js +60 -0
- package/cli/explorer/report.js.map +1 -0
- package/cli/explorer/session.d.ts +449 -0
- package/cli/explorer/session.js +143 -144
- package/cli/explorer/session.js.map +1 -0
- package/cli/explorer/views.d.ts +19 -0
- package/cli/explorer/views.js +465 -482
- package/cli/explorer/views.js.map +1 -0
- package/cli/explorer/wrap.d.ts +1 -0
- package/cli/explorer/wrap.js +28 -44
- package/cli/explorer/wrap.js.map +1 -0
- package/cli/main.d.ts +1 -0
- package/cli/main.js +214 -161
- package/cli/main.js.map +1 -0
- package/cli/prompt.d.ts +5 -0
- package/cli/prompt.js +84 -80
- package/cli/prompt.js.map +1 -0
- package/cli/scanOptions.d.ts +2 -0
- package/cli/scanOptions.js +11 -0
- package/cli/scanOptions.js.map +1 -0
- package/cli/ui.d.ts +33 -0
- package/cli/ui.js +35 -44
- package/cli/ui.js.map +1 -0
- package/cli/wizard.d.ts +187 -0
- package/cli/wizard.js +304 -284
- package/cli/wizard.js.map +1 -0
- package/package.json +15 -4
- package/public/app.d.ts +1 -0
- package/public/app.js +1057 -1009
- package/public/app.js.map +1 -0
- package/public/browser.d.ts +68 -0
- package/public/browser.js +2 -0
- package/public/browser.js.map +1 -0
- package/public/index.html +30 -13
- package/public/js/about.d.ts +6 -0
- package/public/js/about.js +152 -172
- package/public/js/about.js.map +1 -0
- package/public/js/aiDraft.d.ts +3 -0
- package/public/js/aiDraft.js +116 -124
- package/public/js/aiDraft.js.map +1 -0
- package/public/js/analysisPanel.d.ts +7 -0
- package/public/js/analysisPanel.js +166 -166
- package/public/js/analysisPanel.js.map +1 -0
- package/public/js/analysisReport.d.ts +38 -0
- package/public/js/analysisReport.js +105 -110
- package/public/js/analysisReport.js.map +1 -0
- package/public/js/api.d.ts +26 -0
- package/public/js/api.js +176 -167
- package/public/js/api.js.map +1 -0
- package/public/js/atlas.d.ts +6 -0
- package/public/js/atlas.js +50 -58
- package/public/js/atlas.js.map +1 -0
- package/public/js/blameView.d.ts +2 -0
- package/public/js/blameView.js +36 -37
- package/public/js/blameView.js.map +1 -0
- package/public/js/codeTab.d.ts +3 -0
- package/public/js/codeTab.js +175 -180
- package/public/js/codeTab.js.map +1 -0
- package/public/js/codeViewer.d.ts +5 -0
- package/public/js/codeViewer.js +162 -150
- package/public/js/codeViewer.js.map +1 -0
- package/public/js/components/FileChip.d.ts +9 -0
- package/public/js/components/FileChip.js +45 -49
- package/public/js/components/FileChip.js.map +1 -0
- package/public/js/components/MetricSparkline.d.ts +7 -0
- package/public/js/components/MetricSparkline.js +35 -44
- package/public/js/components/MetricSparkline.js.map +1 -0
- package/public/js/components/RiskBadge.d.ts +9 -0
- package/public/js/components/RiskBadge.js +55 -63
- package/public/js/components/RiskBadge.js.map +1 -0
- package/public/js/deepAnalysisView.d.ts +99 -0
- package/public/js/deepAnalysisView.js +282 -302
- package/public/js/deepAnalysisView.js.map +1 -0
- package/public/js/diagramPane.d.ts +8 -0
- package/public/js/diagramPane.js +133 -135
- package/public/js/diagramPane.js.map +1 -0
- package/public/js/diffView.d.ts +6 -0
- package/public/js/diffView.js +222 -209
- package/public/js/diffView.js.map +1 -0
- package/public/js/docsView.d.ts +2 -0
- package/public/js/docsView.js +441 -442
- package/public/js/docsView.js.map +1 -0
- package/public/js/dom.d.ts +189 -0
- package/public/js/dom.js +5 -0
- package/public/js/dom.js.map +1 -0
- package/public/js/fileSourceBrowser.d.ts +5 -0
- package/public/js/fileSourceBrowser.js +33 -41
- package/public/js/fileSourceBrowser.js.map +1 -0
- package/public/js/flameGraph.d.ts +5 -0
- package/public/js/flameGraph.js +62 -72
- package/public/js/flameGraph.js.map +1 -0
- package/public/js/forceGraph.d.ts +10 -0
- package/public/js/forceGraph.js +581 -556
- package/public/js/forceGraph.js.map +1 -0
- package/public/js/heatmap.d.ts +4 -0
- package/public/js/heatmap.js +142 -164
- package/public/js/heatmap.js.map +1 -0
- package/public/js/highlight.d.ts +2 -0
- package/public/js/highlight.js +116 -107
- package/public/js/highlight.js.map +1 -0
- package/public/js/html.d.ts +2 -0
- package/public/js/html.js +14 -44
- package/public/js/html.js.map +1 -0
- package/public/js/insightsView.d.ts +5 -0
- package/public/js/insightsView.js +93 -111
- package/public/js/insightsView.js.map +1 -0
- package/public/js/inspector.d.ts +37 -0
- package/public/js/inspector.js +416 -445
- package/public/js/inspector.js.map +1 -0
- package/public/js/llm.d.ts +113 -0
- package/public/js/llm.js +233 -272
- package/public/js/llm.js.map +1 -0
- package/public/js/mapView.d.ts +3 -0
- package/public/js/mapView.js +121 -120
- package/public/js/mapView.js.map +1 -0
- package/public/js/markdown.d.ts +3 -0
- package/public/js/markdown.js +84 -91
- package/public/js/markdown.js.map +1 -0
- package/public/js/mindmap.d.ts +32 -0
- package/public/js/mindmap.js +244 -259
- package/public/js/mindmap.js.map +1 -0
- package/public/js/mobilePanels.d.ts +5 -0
- package/public/js/mobilePanels.js +50 -0
- package/public/js/mobilePanels.js.map +1 -0
- package/public/js/repoFiles.d.ts +12 -0
- package/public/js/repoFiles.js +28 -27
- package/public/js/repoFiles.js.map +1 -0
- package/public/js/reviewView.d.ts +28 -0
- package/public/js/reviewView.js +256 -0
- package/public/js/reviewView.js.map +1 -0
- package/public/js/sbomView.d.ts +3 -0
- package/public/js/sbomView.js +59 -67
- package/public/js/sbomView.js.map +1 -0
- package/public/js/scanCache.d.ts +16 -0
- package/public/js/scanCache.js +67 -65
- package/public/js/scanCache.js.map +1 -0
- package/public/js/search.d.ts +7 -0
- package/public/js/search.js +868 -800
- package/public/js/search.js.map +1 -0
- package/public/js/searchLocal.d.ts +42 -0
- package/public/js/searchLocal.js +87 -0
- package/public/js/searchLocal.js.map +1 -0
- package/public/js/serverSettings.d.ts +5 -0
- package/public/js/serverSettings.js +153 -164
- package/public/js/serverSettings.js.map +1 -0
- package/public/js/state.d.ts +798 -0
- package/public/js/state.js +114 -122
- package/public/js/state.js.map +1 -0
- package/public/js/tour.d.ts +6 -0
- package/public/js/tour.js +5 -7
- package/public/js/tour.js.map +1 -0
- package/public/js/transitions.d.ts +2 -0
- package/public/js/transitions.js +9 -10
- package/public/js/transitions.js.map +1 -0
- package/public/js/tree.d.ts +12 -0
- package/public/js/tree.js +157 -154
- package/public/js/tree.js.map +1 -0
- package/public/js/workflowsView.d.ts +3 -0
- package/public/js/workflowsView.js +15 -22
- package/public/js/workflowsView.js.map +1 -0
- package/public/search.css +495 -0
- package/public/styles.css +163 -346
- package/public/workbench.css +166 -0
- package/server/apiAuth.d.ts +3 -0
- package/server/apiAuth.js +18 -20
- package/server/apiAuth.js.map +1 -0
- package/server/apiDiff.d.ts +2 -0
- package/server/apiDiff.js +20 -18
- package/server/apiDiff.js.map +1 -0
- package/server/apiDocs.d.ts +2 -0
- package/server/apiDocs.js +38 -40
- package/server/apiDocs.js.map +1 -0
- package/server/apiFile.d.ts +1 -0
- package/server/apiFile.js +14 -17
- package/server/apiFile.js.map +1 -0
- package/server/apiGitBlame.d.ts +2 -0
- package/server/apiGitBlame.js +50 -51
- package/server/apiGitBlame.js.map +1 -0
- package/server/apiMcp.d.ts +4 -0
- package/server/apiMcp.js +64 -66
- package/server/apiMcp.js.map +1 -0
- package/server/apiReview.d.ts +2 -0
- package/server/apiReview.js +45 -0
- package/server/apiReview.js.map +1 -0
- package/server/apiScan.d.ts +5 -0
- package/server/apiScan.js +90 -71
- package/server/apiScan.js.map +1 -0
- package/server/apiSearch.d.ts +33 -0
- package/server/apiSearch.js +184 -200
- package/server/apiSearch.js.map +1 -0
- package/server/apiSettings.d.ts +4 -0
- package/server/apiSettings.js +84 -85
- package/server/apiSettings.js.map +1 -0
- package/server/apiTools.d.ts +3 -0
- package/server/apiTools.js +55 -56
- package/server/apiTools.js.map +1 -0
- package/server/auth.d.ts +5 -0
- package/server/auth.js +54 -51
- package/server/auth.js.map +1 -0
- package/server/config.d.ts +42 -0
- package/server/config.js +189 -194
- package/server/config.js.map +1 -0
- package/server/daemon.d.ts +12 -0
- package/server/daemon.js +124 -114
- package/server/daemon.js.map +1 -0
- package/server/fileSourceNode.d.ts +2 -0
- package/server/fileSourceNode.js +34 -36
- package/server/fileSourceNode.js.map +1 -0
- package/server/gitClone.d.ts +9 -0
- package/server/gitClone.js +59 -61
- package/server/gitClone.js.map +1 -0
- package/server/gitDiff.d.ts +36 -0
- package/server/gitDiff.js +271 -169
- package/server/gitDiff.js.map +1 -0
- package/server/gitHistory.d.ts +12 -0
- package/server/gitHistory.js +80 -80
- package/server/gitHistory.js.map +1 -0
- package/server/gitRemote.d.ts +12 -0
- package/server/gitRemote.js +37 -38
- package/server/gitRemote.js.map +1 -0
- package/server/htmlText.d.ts +4 -0
- package/server/htmlText.js +16 -23
- package/server/htmlText.js.map +1 -0
- package/server/http.d.ts +5 -0
- package/server/http.js +27 -30
- package/server/http.js.map +1 -0
- package/server/httpGuards.d.ts +2 -0
- package/server/httpGuards.js +47 -43
- package/server/httpGuards.js.map +1 -0
- package/server/https.d.ts +34 -0
- package/server/https.js +121 -111
- package/server/https.js.map +1 -0
- package/server/index.d.ts +40 -0
- package/server/index.js +139 -147
- package/server/index.js.map +1 -0
- package/server/layout.d.ts +26 -0
- package/server/layout.js +59 -64
- package/server/layout.js.map +1 -0
- package/server/llmProxy.d.ts +3 -0
- package/server/llmProxy.js +137 -135
- package/server/llmProxy.js.map +1 -0
- package/server/logger.d.ts +38 -0
- package/server/logger.js +198 -211
- package/server/logger.js.map +1 -0
- package/server/mcp/analysis.d.ts +29 -0
- package/server/mcp/analysis.js +99 -120
- package/server/mcp/analysis.js.map +1 -0
- package/server/mcp/http.d.ts +9 -0
- package/server/mcp/http.js +128 -137
- package/server/mcp/http.js.map +1 -0
- package/server/mcp/runner.d.ts +68 -0
- package/server/mcp/runner.js +208 -218
- package/server/mcp/runner.js.map +1 -0
- package/server/mcp/server.d.ts +29 -0
- package/server/mcp/server.js +166 -179
- package/server/mcp/server.js.map +1 -0
- package/server/mcp/standalone.d.ts +1 -0
- package/server/mcp/standalone.js +8 -10
- package/server/mcp/standalone.js.map +1 -0
- package/server/mcp/tools.d.ts +2020 -0
- package/server/mcp/tools.js +523 -574
- package/server/mcp/tools.js.map +1 -0
- package/server/paths.d.ts +3 -0
- package/server/paths.js +17 -15
- package/server/paths.js.map +1 -0
- package/server/pidfile.d.ts +9 -0
- package/server/pidfile.js +43 -45
- package/server/pidfile.js.map +1 -0
- package/server/review.d.ts +5 -0
- package/server/review.js +35 -0
- package/server/review.js.map +1 -0
- package/server/router.d.ts +33 -0
- package/server/router.js +191 -197
- package/server/router.js.map +1 -0
- package/server/scanRequest.d.ts +3 -0
- package/server/scanRequest.js +36 -0
- package/server/scanRequest.js.map +1 -0
- package/server/searchIndex.d.ts +17 -0
- package/server/searchIndex.js +83 -80
- package/server/searchIndex.js.map +1 -0
- package/server/sessions.d.ts +14 -0
- package/server/sessions.js +62 -70
- package/server/sessions.js.map +1 -0
- package/server/startup.d.ts +118 -0
- package/server/startup.js +143 -148
- package/server/startup.js.map +1 -0
- package/server/static.d.ts +6 -0
- package/server/static.js +28 -31
- package/server/static.js.map +1 -0
- package/server/tools/install.d.ts +4 -0
- package/server/tools/install.js +176 -185
- package/server/tools/install.js.map +1 -0
- package/server/tools/parse.d.ts +8 -0
- package/server/tools/parse.js +112 -114
- package/server/tools/parse.js.map +1 -0
- package/server/tools/platform.d.ts +9 -0
- package/server/tools/platform.js +49 -47
- package/server/tools/platform.js.map +1 -0
- package/server/tools/registry.d.ts +137 -0
- package/server/tools/registry.js +173 -172
- package/server/tools/registry.js.map +1 -0
- package/server/tools/scan.d.ts +34 -0
- package/server/tools/scan.js +89 -98
- package/server/tools/scan.js.map +1 -0
- package/server/tools.d.ts +34 -0
- package/server/tools.js +94 -107
- package/server/tools.js.map +1 -0
- package/server/tunnel.d.ts +29 -0
- package/server/tunnel.js +61 -66
- package/server/tunnel.js.map +1 -0
- package/shared/analyzer/docs.d.ts +16 -0
- package/shared/analyzer/docs.js +99 -93
- package/shared/analyzer/docs.js.map +1 -0
- package/shared/analyzer/explainLocal.d.ts +4 -0
- package/shared/analyzer/explainLocal.js +122 -142
- package/shared/analyzer/explainLocal.js.map +1 -0
- package/shared/analyzer/github.d.ts +37 -0
- package/shared/analyzer/github.js +41 -43
- package/shared/analyzer/github.js.map +1 -0
- package/shared/analyzer/graph.d.ts +41 -0
- package/shared/analyzer/graph.js +393 -400
- package/shared/analyzer/graph.js.map +1 -0
- package/shared/analyzer/health.d.ts +33 -0
- package/shared/analyzer/health.js +197 -193
- package/shared/analyzer/health.js.map +1 -0
- package/shared/analyzer/history.d.ts +29 -0
- package/shared/analyzer/history.js +110 -111
- package/shared/analyzer/history.js.map +1 -0
- package/shared/analyzer/jsonConfig.d.ts +2 -0
- package/shared/analyzer/jsonConfig.js +61 -0
- package/shared/analyzer/jsonConfig.js.map +1 -0
- package/shared/analyzer/languages/csharp.d.ts +26 -0
- package/shared/analyzer/languages/csharp.js +83 -88
- package/shared/analyzer/languages/csharp.js.map +1 -0
- package/shared/analyzer/languages/generic.d.ts +23 -0
- package/shared/analyzer/languages/generic.js +94 -105
- package/shared/analyzer/languages/generic.js.map +1 -0
- package/shared/analyzer/languages/go.d.ts +24 -0
- package/shared/analyzer/languages/go.js +45 -54
- package/shared/analyzer/languages/go.js.map +1 -0
- package/shared/analyzer/languages/index.d.ts +6 -0
- package/shared/analyzer/languages/index.js +19 -20
- package/shared/analyzer/languages/index.js.map +1 -0
- package/shared/analyzer/languages/java.d.ts +20 -0
- package/shared/analyzer/languages/java.js +73 -78
- package/shared/analyzer/languages/java.js.map +1 -0
- package/shared/analyzer/languages/javascript.d.ts +12 -0
- package/shared/analyzer/languages/javascript.js +258 -209
- package/shared/analyzer/languages/javascript.js.map +1 -0
- package/shared/analyzer/languages/python.d.ts +23 -0
- package/shared/analyzer/languages/python.js +92 -100
- package/shared/analyzer/languages/python.js.map +1 -0
- package/shared/analyzer/languages/rust.d.ts +17 -0
- package/shared/analyzer/languages/rust.js +96 -98
- package/shared/analyzer/languages/rust.js.map +1 -0
- package/shared/analyzer/languages/typescript.d.ts +11 -0
- package/shared/analyzer/languages/typescript.js +117 -116
- package/shared/analyzer/languages/typescript.js.map +1 -0
- package/shared/analyzer/licenses.d.ts +18 -0
- package/shared/analyzer/licenses.js +130 -133
- package/shared/analyzer/licenses.js.map +1 -0
- package/shared/analyzer/metrics.d.ts +20 -0
- package/shared/analyzer/metrics.js +112 -104
- package/shared/analyzer/metrics.js.map +1 -0
- package/shared/analyzer/pathUtil.d.ts +10 -0
- package/shared/analyzer/pathUtil.js +29 -35
- package/shared/analyzer/pathUtil.js.map +1 -0
- package/shared/analyzer/patterns.d.ts +11 -0
- package/shared/analyzer/patterns.js +231 -253
- package/shared/analyzer/patterns.js.map +1 -0
- package/shared/analyzer/scan.d.ts +62 -0
- package/shared/analyzer/scan.js +451 -442
- package/shared/analyzer/scan.js.map +1 -0
- package/shared/analyzer/scanControl.d.ts +11 -0
- package/shared/analyzer/scanControl.js +62 -0
- package/shared/analyzer/scanControl.js.map +1 -0
- package/shared/analyzer/security.d.ts +18 -0
- package/shared/analyzer/security.js +159 -159
- package/shared/analyzer/security.js.map +1 -0
- package/shared/analyzer/services.d.ts +5 -0
- package/shared/analyzer/services.js +141 -138
- package/shared/analyzer/services.js.map +1 -0
- package/shared/analyzer/stack.d.ts +6 -0
- package/shared/analyzer/stack.js +134 -141
- package/shared/analyzer/stack.js.map +1 -0
- package/shared/analyzer/tour.d.ts +2 -0
- package/shared/analyzer/tour.js +45 -53
- package/shared/analyzer/tour.js.map +1 -0
- package/shared/analyzer/util.d.ts +8 -0
- package/shared/analyzer/util.js +130 -76
- package/shared/analyzer/util.js.map +1 -0
- package/shared/analyzer/workflows.d.ts +8 -0
- package/shared/analyzer/workflows.js +139 -134
- package/shared/analyzer/workflows.js.map +1 -0
- package/shared/contracts.d.ts +250 -0
- package/shared/contracts.js +2 -0
- package/shared/contracts.js.map +1 -0
- package/shared/diagram/aiFacts.d.ts +35 -0
- package/shared/diagram/aiFacts.js +102 -105
- package/shared/diagram/aiFacts.js.map +1 -0
- package/shared/diagram/aiMermaid.d.ts +5 -0
- package/shared/diagram/aiMermaid.js +46 -45
- package/shared/diagram/aiMermaid.js.map +1 -0
- package/shared/diagram/atlas.d.ts +16 -0
- package/shared/diagram/atlas.js +51 -60
- package/shared/diagram/atlas.js.map +1 -0
- package/shared/diagram/mermaid.d.ts +43 -0
- package/shared/diagram/mermaid.js +348 -370
- package/shared/diagram/mermaid.js.map +1 -0
- package/shared/review/contracts.d.ts +95 -0
- package/shared/review/contracts.js +2 -0
- package/shared/review/contracts.js.map +1 -0
- package/shared/review/review.d.ts +10 -0
- package/shared/review/review.js +184 -0
- package/shared/review/review.js.map +1 -0
- package/shared/search/query.d.ts +32 -0
- package/shared/search/query.js +395 -388
- 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
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
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 =
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
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
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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":"AAAA,0EAA0E;AAC1E,8EAA8E;AAC9E,uEAAuE;AAEvE,MAAM,KAAK,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;AAE3D,MAAM,UAAU,aAAa,CAAC,IAAI,EAAE,KAAK;IACvC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IACzB,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACvC,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;IACvB,6EAA6E;IAC7E,2DAA2D;IAC3D,IAAI,CAAC,CAAC,EAAE,CAAC;QACP,OAAO;YACL,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI;YACpE,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;SAClE,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,GAAG,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IACvC,IAAI,KAAK,GAAG,IAAI,CAAC;IACjB,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK;YAAE,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;IACnC,CAAC;IAED,0EAA0E;IAC1E,wEAAwE;IACxE,6EAA6E;IAC7E,wEAAwE;IACxE,MAAM,KAAK,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAChE,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAEvC,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QAC9B,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;QACjB,MAAM,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,WAAW,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QACvD,MAAM,EAAE,GAAG,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC;QAC7B,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;QACjC,MAAM,UAAU,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC;QACxC,MAAM,IAAI,GAAG,KAAK,CAChB,IAAI,CAAC,KAAK,CACR,EAAE,GAAG,UAAU,GAAa,gCAAgC;YAC5D,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,GAAK,kCAAkC;YAChE,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,+BAA+B;YAC/D,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,EAAE,CAAC,CAAC,GAAG,2BAA2B;YACzD,CAAC,GAAG,WAAW,CAAe,yCAAyC;SACxE,EACD,CAAC,EACD,GAAG,CACJ,CAAC;QACF,OAAO;YACL,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI;YAC3B,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,GAAG,CAAC,GAAG,GAAG;YAC9C,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;YAC5B,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,GAAG,CAAC,GAAG,GAAG;YAChD,UAAU,EAAE,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;SACpE,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;IAExC,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;IACxD,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,IAAI,CAAC,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC;IACvE,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;IAChE,MAAM,WAAW,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IAEpD,yDAAyD;IACzD,MAAM,SAAS,GAAG,EAAE,CAAC;IACrB,IAAI,KAAK,GAAG,GAAG,CAAC;IAChB,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;QAC7B,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC7B,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAAC,KAAK,IAAI,CAAC,CAAC;YAAC,SAAS,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QAAC,CAAC;IACpE,CAAC,CAAC;IACF,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC,CAAC;IAC7C,IAAI,CAAC,UAAU,GAAG,CAAC,EAAE,GAAG,UAAU,aAAa,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC;IACnG,IAAI,CAAC,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,EAAE,GAAG,IAAI,eAAe,IAAI,kBAAkB,IAAI,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;IACtG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,sBAAsB,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IAC/F,IAAI,CAAC,WAAW,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,GAAG,CAAC,wBAAwB,CAAC,CAAC;IACjF,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;IAClG,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,CAAC,oBAAoB,GAAG,EAAE;YAAE,KAAK,EAAE,CAAC;QACzC,IAAI,CAAC,CAAC,MAAM;YAAE,WAAW,IAAI,CAAC,CAAC,MAAM,CAAC;IACxC,CAAC;IACD,MAAM,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACxC,MAAM,WAAW,GAAG,WAAW,GAAG,IAAI,CAAC;IACvC,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,IAAI,aAAa,GAAG,GAAG;QAAE,YAAY,GAAG,UAAU,CAAC;SAC9C,IAAI,aAAa,GAAG,IAAI;QAAE,YAAY,GAAG,MAAM,CAAC;SAChD,IAAI,aAAa,GAAG,IAAI;QAAE,YAAY,GAAG,UAAU,CAAC;IAGvD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,EAAE,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC;AACjO,CAAC;AAED,0EAA0E;AAC1E,mEAAmE;AACnE,SAAS,QAAQ,CAAC,KAAK,EAAE,KAAK;IAC5B,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;IACvB,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5D,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;IAChD,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjC,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACtB,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACpB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI;YAAE,SAAS;QACrC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACf,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IACX,CAAC;IACD,IAAI,IAAI,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACpC,MAAM,CAAC,GAAG,IAAI,CAAC;IACf,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YAC5C,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;gBAAE,IAAI,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC;QAC3C,CAAC;QACD,IAAI,GAAG,IAAI,CAAC;IACd,CAAC;IACD,MAAM,GAAG,GAAwB,EAAE,CAAC;IACpC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5C,OAAO,GAAG,CAAC;AACb,CAAC;AAED,yEAAyE;AACzE,0DAA0D;AAC1D,SAAS,WAAW,CAAC,KAAK,EAAE,KAAK;IAC/B,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;IACvB,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5D,qEAAqE;IACrE,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;IACjD,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACtB,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACpB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI;YAAE,SAAS;QACrC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAG,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;IACnE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACpB,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;YAAE,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC;gBAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAClF,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAE,CAAC;IACvB,MAAM,KAAK,GAAG,CAAC,CAAC,EAAE,EAAE;QAClB,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACpC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACzB,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC;YAAE,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC;gBAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACjE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QACjB,OAAO,GAAG,CAAC;IACb,CAAC,CAAC;IACF,MAAM,KAAK,GAAwB,EAAE,CAAC;IACtC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACrB,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAAE,KAAK,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC;QACrD,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe;IACvD,CAAC,CAAC,CAAC;IACH,OAAO,KAAK,CAAC;AACf,CAAC;AAED,wDAAwD;AACxD,SAAS,MAAM,CAAC,CAAC,EAAE,GAAG;IACpB,MAAM,IAAI,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACpC,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjC,MAAM,OAAO,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,EAAE,CAAC;IACjB,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YAAE,SAAS;QAC9B,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACtB,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;YACnB,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAClC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;YACjB,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;YACf,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBACZ,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC;gBAC1B,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBACd,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;YACpB,CAAC;YACD,IAAI,MAAM,GAAG,KAAK,CAAC;YACnB,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC9B,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACpB,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;oBACpB,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;oBACf,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;oBAClB,MAAM,GAAG,IAAI,CAAC;oBACd,MAAM;gBACR,CAAC;gBACD,IAAI,OAAO,CAAC,CAAC,CAAC;oBAAE,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YACtD,CAAC;YACD,IAAI,MAAM;gBAAE,SAAS;YACrB,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;gBACxB,IAAI,CAAC,CAAC;gBACN,GAAG,CAAC;oBACF,CAAC,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC;oBAChB,OAAO,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;oBACnB,IAAI,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;gBACtB,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE;gBAClB,SAAS,EAAE,CAAC;YACd,CAAC;YACD,IAAI,CAAC,GAAG,EAAE,CAAC;YACX,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBAChB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACxC,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9C,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;AAC7B,CAAC","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
|
+
};
|