Identify structural weaknesses in the codebase graph. Returns dict with categories: - isolated_nodes: degree <= 1, disconnected from graph - thin_communities: fewer than 3 members - untested_hotspots: high-degree nodes with no TESTED_BY edges - single_file_communities: entire co
(store: GraphStore)
| 113 | |
| 114 | |
| 115 | def find_knowledge_gaps(store: GraphStore) -> dict[str, list[dict]]: |
| 116 | """Identify structural weaknesses in the codebase graph. |
| 117 | |
| 118 | Returns dict with categories: |
| 119 | - isolated_nodes: degree <= 1, disconnected from graph |
| 120 | - thin_communities: fewer than 3 members |
| 121 | - untested_hotspots: high-degree nodes with no TESTED_BY edges |
| 122 | - single_file_communities: entire community in one file |
| 123 | """ |
| 124 | edges = store.get_all_edges() |
| 125 | nodes = store.get_all_nodes(exclude_files=True) |
| 126 | community_map = store.get_all_community_ids() |
| 127 | |
| 128 | # Build degree map |
| 129 | degree: dict[str, int] = Counter() |
| 130 | tested_nodes: set[str] = set() |
| 131 | for e in edges: |
| 132 | degree[e.source_qualified] += 1 |
| 133 | degree[e.target_qualified] += 1 |
| 134 | if e.kind == "TESTED_BY": |
| 135 | tested_nodes.add(e.source_qualified) |
| 136 | |
| 137 | # 1. Isolated nodes (degree <= 1, not File) |
| 138 | isolated = [] |
| 139 | for n in nodes: |
| 140 | d = degree.get(n.qualified_name, 0) |
| 141 | if d <= 1: |
| 142 | isolated.append({ |
| 143 | "name": _sanitize_name(n.name), |
| 144 | "qualified_name": n.qualified_name, |
| 145 | "kind": n.kind, |
| 146 | "file": n.file_path, |
| 147 | "degree": d, |
| 148 | }) |
| 149 | |
| 150 | # 2. Build community sizes and file maps from node data |
| 151 | comm_sizes: Counter[int] = Counter() |
| 152 | comm_files: dict[int, set[str]] = defaultdict(set) |
| 153 | for n in nodes: |
| 154 | cid = community_map.get(n.qualified_name) |
| 155 | if cid is not None: |
| 156 | comm_sizes[cid] += 1 |
| 157 | comm_files[cid].add(n.file_path) |
| 158 | |
| 159 | # Thin communities (< 3 members) |
| 160 | communities = store.get_communities_list() |
| 161 | thin = [] |
| 162 | for c in communities: |
| 163 | cid = int(c["id"]) |
| 164 | size = comm_sizes.get(cid, 0) |
| 165 | if size < 3: |
| 166 | thin.append({ |
| 167 | "community_id": cid, |
| 168 | "name": str(c["name"]), |
| 169 | "size": size, |
| 170 | }) |
| 171 | |
| 172 | # 3. Untested hotspots (degree >= 5, no TESTED_BY) |
no test coverage detected