Skip to content

Commit f2aee96

Browse files
scgopiclaude
andcommitted
The sidebar anchors closed cycles the way the canvas always has
A maker↔reviewer pair — forward edge one way, guarded back-edge the other — has no node without an inbound edge, and the sidebar's row tree walked only from no-inbound roots: the whole cycle vanished from the list while both loops ran. The canvas never had the bug, because LoopGraph.startAnchors already anchors each cycle-only component at its first node. The sidebar now consumes startAnchors instead of keeping its own weaker definition of "root", so the two views can never again disagree about which loops exist. The graph-level behaviour was already pinned by aClosedCycleIsAnchoredAtItsFirstNodeRatherThanNotAtAll. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 9751efd commit f2aee96

1 file changed

Lines changed: 10 additions & 5 deletions

File tree

graphcode/Sources/Features/App/AppSidebarView+Rows.swift

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -178,12 +178,17 @@ extension AppSidebarView {
178178
}
179179
}
180180

181-
/// This project's top-level rows — nodes nothing points at — in the human's
182-
/// arrangement (`sidebarNodeOrder`), not the graph's insertion order.
181+
/// This project's top-level rows, in the human's arrangement (`sidebarNodeOrder`).
182+
///
183+
/// `startAnchors`, not a bare "nodes nothing points at" filter — the difference is a
184+
/// bug this row tree had and the canvas never did: a closed cycle (a maker↔reviewer
185+
/// pair, forward edge one way, guarded back-edge the other) has no node without an
186+
/// inbound edge, so a walk from no-inbound roots alone dropped the whole cycle from
187+
/// the sidebar — two loops running, neither listed. `startAnchors` anchors each
188+
/// cycle-only component at its first node, and reusing it means the sidebar and the
189+
/// canvas can never again disagree about which nodes exist.
183190
func orderedRootNodes(in project: ProjectFeature.State) -> [LoopNode] {
184-
let roots = project.graph.nodes.filter { node in
185-
!project.graph.edges.contains { $0.to == node.id }
186-
}
191+
let roots = project.graph.startAnchors.compactMap { project.graph.nodes[id: $0] }
187192
let order = project.sidebarNodeOrder
188193
return roots.sorted { a, b in
189194
(order.firstIndex(of: a.id) ?? .max) < (order.firstIndex(of: b.id) ?? .max)

0 commit comments

Comments
 (0)