# UNDF: UNDF-2026-000000234
Fixes pyramid-0004: util.py TopologicalSorter.sorted() — list used as queue with O(n) pop(0)/insert(0) and O(n) roots membership + remove().

--- a/src/pyramid/util.py
+++ b/src/pyramid/util.py

@@ DEFECT pyramid-0004: TopologicalSorter.sorted() lines 503-561

+from collections import deque

 def sorted(self):
     order = [(self.first, self.last)]
-    roots = []                          # list — O(n) pop(0)/insert(0)/in/remove — CWE-407
+    roots = deque()                     # FIX pyramid-0004: deque for O(1) popleft/appendleft
+    roots_set = set()                   # FIX pyramid-0004: O(1) membership test
     graph = {}

     def add_node(node):
         if node not in graph:
-            roots.append(node)
+            roots.append(node)          # O(1) deque append
+            roots_set.add(node)
             graph[node] = [0]

     def add_arc(fromnode, tonode):
         graph[fromnode].append(tonode)
         graph[tonode][0] += 1
-        if tonode in roots:             # O(n) list scan — CWE-407
-            roots.remove(tonode)        # O(n) list removal — CWE-407
+        if tonode in roots_set:         # O(1) set lookup — fixed
+            roots.remove(tonode)        # O(n) deque remove — still needed; rare case
+            roots_set.discard(tonode)

     # ... (node/arc setup unchanged) ...

     sorted_names = []
     while roots:
-        root = roots.pop(0)            # O(n) list pop from front — CWE-407
+        root = roots.popleft()         # O(1) deque popleft — fixed
+        roots_set.discard(root)
         sorted_names.append(root)
         children = graph[root][1:]
         for child in children:
             arcs = graph[child][0]
             arcs -= 1
             graph[child][0] = arcs
             if arcs == 0:
-                roots.insert(0, child)  # O(n) list insert at front — CWE-407
+                roots.appendleft(child) # O(1) deque appendleft — fixed
+                roots_set.add(child)
         del graph[root]

# SUMMARY: Four O(n) list operations replaced:
#   roots.pop(0)    → roots.popleft()     O(n) → O(1)
#   roots.insert(0) → roots.appendleft()  O(n) → O(1)
#   tonode in roots → tonode in roots_set O(n) → O(1)
#   roots.remove()  → roots.remove()      O(n) → O(n) [rare; deque.remove still O(n)]
# Net: O(E²) → O(E log E) or better for most tween/deriver graphs.
