(data: PRGraphData)
| 95 | } |
| 96 | |
| 97 | export function computePRInsights(data: PRGraphData): PRInsights { |
| 98 | const nodes = data.nodes || []; |
| 99 | const links = data.links || []; |
| 100 | const directNodes = nodes.filter((n) => n.prZone === "direct"); |
| 101 | const primaryNodes = nodes.filter((n) => n.prZone === "primary"); |
| 102 | |
| 103 | const signalNodes = directNodes.filter((n) => !isLikelyNoiseNode(n, directNodes)); |
| 104 | const noiseNodes = directNodes.filter((n) => isLikelyNoiseNode(n, directNodes)); |
| 105 | const noiseRatio = directNodes.length |
| 106 | ? Math.round((noiseNodes.length / directNodes.length) * 100) |
| 107 | : 0; |
| 108 | |
| 109 | const addedSymbols = signalNodes.filter((n) => n.status === "added"); |
| 110 | const modifiedSymbols = signalNodes.filter( |
| 111 | (n) => n.status === "modified" && (n.type === "Function" || n.type === "Class") |
| 112 | ); |
| 113 | |
| 114 | const keySymbols: PRKeySymbol[] = []; |
| 115 | const seen = new Set<string>(); |
| 116 | |
| 117 | for (const node of [...addedSymbols, ...modifiedSymbols]) { |
| 118 | if (seen.has(node.id)) continue; |
| 119 | if (isLikelyNoiseNode(node, directNodes)) continue; |
| 120 | seen.add(node.id); |
| 121 | keySymbols.push({ |
| 122 | id: node.id, |
| 123 | name: node.name, |
| 124 | file: node.file, |
| 125 | reason: |
| 126 | node.status === "added" |
| 127 | ? "New symbol added in this PR" |
| 128 | : "Directly modified function/class", |
| 129 | }); |
| 130 | } |
| 131 | |
| 132 | for (const link of links) { |
| 133 | const targetId = typeof link.target === "object" ? (link.target as any).id : link.target; |
| 134 | const target = nodes.find((n) => n.id === targetId); |
| 135 | if (!target || target.prZone !== "direct") continue; |
| 136 | if (seen.has(target.id)) continue; |
| 137 | if (isLikelyNoiseNode(target, directNodes)) continue; |
| 138 | seen.add(target.id); |
| 139 | keySymbols.push({ |
| 140 | id: target.id, |
| 141 | name: target.name, |
| 142 | file: target.file, |
| 143 | reason: "Downstream target of a call edge in the impact graph", |
| 144 | }); |
| 145 | } |
| 146 | |
| 147 | const meaningfulCallPaths: PRCallPath[] = links |
| 148 | .filter((l) => { |
| 149 | const sId = typeof l.source === "object" ? (l.source as any).id : l.source; |
| 150 | const tId = typeof l.target === "object" ? (l.target as any).id : l.target; |
| 151 | const source = nodes.find((n) => n.id === sId); |
| 152 | const target = nodes.find((n) => n.id === tId); |
| 153 | if (!source || !target) return false; |
| 154 | const touchesChange = |
no test coverage detected