(fileMetrics: FileMetrics)
| 112 | } |
| 113 | |
| 114 | function getHealthLevel(fileMetrics: FileMetrics): CodebaseHealthFile { |
| 115 | const reasons: string[] = []; |
| 116 | let score = 0; |
| 117 | |
| 118 | if (fileMetrics.cycleCount > 0) { |
| 119 | score += 3; |
| 120 | reasons.push( |
| 121 | `Participates in ${fileMetrics.cycleCount} circular dependenc${fileMetrics.cycleCount === 1 ? 'y' : 'ies'}` |
| 122 | ); |
| 123 | } |
| 124 | |
| 125 | if (fileMetrics.importerCount >= 8) { |
| 126 | score += 2; |
| 127 | reasons.push(`High fan-in: ${fileMetrics.importerCount} files depend on it`); |
| 128 | } else if (fileMetrics.importerCount >= 4) { |
| 129 | score += 1; |
| 130 | reasons.push(`Shared dependency for ${fileMetrics.importerCount} files`); |
| 131 | } |
| 132 | |
| 133 | if (fileMetrics.hotspotRank && fileMetrics.hotspotRank <= 5) { |
| 134 | score += 2; |
| 135 | reasons.push(`Hotspot rank #${fileMetrics.hotspotRank} by graph centrality`); |
| 136 | } else if (fileMetrics.hotspotRank && fileMetrics.hotspotRank <= 10) { |
| 137 | score += 1; |
| 138 | reasons.push(`Top-10 hotspot by graph centrality`); |
| 139 | } |
| 140 | |
| 141 | if (fileMetrics.maxCyclomaticComplexity >= 18) { |
| 142 | score += 2; |
| 143 | reasons.push(`Complex implementation (cyclomatic ${fileMetrics.maxCyclomaticComplexity})`); |
| 144 | } else if (fileMetrics.maxCyclomaticComplexity >= 10) { |
| 145 | score += 1; |
| 146 | reasons.push(`Moderate code complexity (cyclomatic ${fileMetrics.maxCyclomaticComplexity})`); |
| 147 | } |
| 148 | |
| 149 | const level = score >= 4 ? 'high' : score >= 2 ? 'medium' : ('low' as const); |
| 150 | |
| 151 | return { |
| 152 | file: '', |
| 153 | level, |
| 154 | score, |
| 155 | reasons: reasons.slice(0, 3), |
| 156 | signals: { |
| 157 | ...(fileMetrics.hotspotRank ? { hotspotRank: fileMetrics.hotspotRank } : {}), |
| 158 | ...(fileMetrics.importerCount > 0 ? { importerCount: fileMetrics.importerCount } : {}), |
| 159 | ...(fileMetrics.importCount > 0 ? { importCount: fileMetrics.importCount } : {}), |
| 160 | ...(fileMetrics.cycleCount > 0 ? { cycleCount: fileMetrics.cycleCount } : {}), |
| 161 | ...(fileMetrics.maxCyclomaticComplexity > 0 |
| 162 | ? { maxCyclomaticComplexity: fileMetrics.maxCyclomaticComplexity } |
| 163 | : {}) |
| 164 | } |
| 165 | }; |
| 166 | } |
| 167 | |
| 168 | export function deriveCodebaseHealth({ |
| 169 | buildId, |
no outgoing calls
no test coverage detected