# graph/critical_path.py def compute_critical_path(actions): """ Computes the longest dependency-weighted path in a build DAG. This represents the true bottleneck chain ("critical path") that determines total build time. """ # ----------------------------- # Build adjacency + cost map # ----------------------------- graph = {} duration = {} for action in actions: name = action["name"] deps = action.get("deps", []) graph[name] = deps # fallback cost model (later replace with real timing data) duration[name] = action.get("cost", 1) # ----------------------------- # memoized DFS for longest path # ----------------------------- memo = {} def dfs(node): if node in memo: return memo[node] # leaf node if node not in graph or not graph[node]: memo[node] = duration.get(node, 1) return memo[node] best_dep = 0 for dep in graph[node]: best_dep = max(best_dep, dfs(dep)) memo[node] = best_dep + duration.get(node, 1) return memo[node] # ----------------------------- # find worst (critical) endpoint # ----------------------------- critical_node = None critical_score = -1 for node in graph.keys(): score = dfs(node) if score > critical_score: critical_score = score critical_node = node return { "critical_node": critical_node, "critical_score": critical_score, "score_map": memo }