From 44e72f919dca20d37eca86a447f3a3ea3482d6dc Mon Sep 17 00:00:00 2001 From: Michael Porter Date: Sun, 11 Oct 2026 20:55:46 -0400 Subject: [PATCH] fix(graph): return outgoing edges in document order MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit petgraph prepends each new edge to a node's adjacency list, so get_outgoing_edges / get_filtered_outgoing_edges (and the grouped variant) returned a note's edges newest-first. Anything taking the first match — 'Jump to first neighbour', PrevNextView, walk_to_roots — picked the last field in the note instead of the first. Reverse to restore insertion order. traverse_note's iterative DFS emitted children in reverse link order, which the old reversed graph order happened to cancel out; push children in reverse so it keeps link order. Refs #790 --- src/graph/builders/explicit/traverse_note.ts | 3 +- tests/graph/builders/traverse_note.test.ts | 8 ++++ wasm/pkg/breadcrumbs_graph_wasm.d.ts | 5 +- wasm/pkg/breadcrumbs_graph_wasm.js | 5 +- wasm/pkg/breadcrumbs_graph_wasm_bg.wasm | Bin 334041 -> 334105 bytes wasm/src/graph.rs | 36 +++++++------- wasm/tests/queries.rs | 47 +++++++++++++++++++ 7 files changed, 81 insertions(+), 23 deletions(-) diff --git a/src/graph/builders/explicit/traverse_note.ts b/src/graph/builders/explicit/traverse_note.ts index 6f2d731f..a5db4de5 100644 --- a/src/graph/builders/explicit/traverse_note.ts +++ b/src/graph/builders/explicit/traverse_note.ts @@ -24,7 +24,8 @@ function dfs_edges( if (visited.has(item.node)) continue; visited.add(item.node); if (item.parent !== null) edges.push([item.parent, item.node]); - for (const child of Object.keys(links[item.node] ?? {})) { + // Push in reverse so the stack pops children in link order (#790). + for (const child of Object.keys(links[item.node] ?? {}).reverse()) { if (!visited.has(child)) { stack.push({ node: child, parent: item.node }); } diff --git a/tests/graph/builders/traverse_note.test.ts b/tests/graph/builders/traverse_note.test.ts index e55e541e..9b9688bb 100644 --- a/tests/graph/builders/traverse_note.test.ts +++ b/tests/graph/builders/traverse_note.test.ts @@ -37,6 +37,14 @@ describe("traverse_note builder", () => { t.expect(r.edges.every((e) => e.edge_type === "up")).toBe(true); }); + test("children are emitted in link order (#790)", async (t) => { + const r = await _add_explicit_edges_traverse_note( + plugin({ "A.md": { "B.md": 1, "C.md": 1, "D.md": 1 } }), + make_all_files([mock_file("A.md", { frontmatter: FIELD })]), + ); + t.expect(r.edges.map((e) => e.target)).toEqual(["B.md", "C.md", "D.md"]); + }); + test("cycles are not revisited", async (t) => { const r = await _add_explicit_edges_traverse_note( plugin({ "A.md": { "B.md": 1 }, "B.md": { "A.md": 1 } }), diff --git a/wasm/pkg/breadcrumbs_graph_wasm.d.ts b/wasm/pkg/breadcrumbs_graph_wasm.d.ts index 1c0e02f1..690fa5c9 100644 --- a/wasm/pkg/breadcrumbs_graph_wasm.d.ts +++ b/wasm/pkg/breadcrumbs_graph_wasm.d.ts @@ -235,7 +235,8 @@ export class NoteGraph { */ get_filtered_grouped_outgoing_edges(node: string, edge_types?: string[] | null): GroupedEdgeList; /** - * Get all outgoing edges from a node, filtered by edge type. + * Get all outgoing edges from a node, filtered by edge type, in insertion + * (document) order. */ get_filtered_outgoing_edges(node: string, edge_types?: string[] | null): EdgeList; /** @@ -244,7 +245,7 @@ export class NoteGraph { get_incoming_edges(node: string): EdgeList; get_node(node: string): NodeData | undefined; /** - * Get all outgoing edges from a node. + * Get all outgoing edges from a node, in insertion (document) order. */ get_outgoing_edges(node: string): EdgeList; /** diff --git a/wasm/pkg/breadcrumbs_graph_wasm.js b/wasm/pkg/breadcrumbs_graph_wasm.js index 09b71f62..247288ae 100644 --- a/wasm/pkg/breadcrumbs_graph_wasm.js +++ b/wasm/pkg/breadcrumbs_graph_wasm.js @@ -1604,7 +1604,8 @@ export class NoteGraph { return GroupedEdgeList.__wrap(ret); } /** - * Get all outgoing edges from a node, filtered by edge type. + * Get all outgoing edges from a node, filtered by edge type, in insertion + * (document) order. * @param {string} node * @param {string[] | null} [edge_types] * @returns {EdgeList} @@ -1639,7 +1640,7 @@ export class NoteGraph { return ret === 0 ? undefined : NodeData.__wrap(ret); } /** - * Get all outgoing edges from a node. + * Get all outgoing edges from a node, in insertion (document) order. * @param {string} node * @returns {EdgeList} */ diff --git a/wasm/pkg/breadcrumbs_graph_wasm_bg.wasm b/wasm/pkg/breadcrumbs_graph_wasm_bg.wasm index 050c3942a394c20f6f856e95b476018e00b5c578..18011eb14f6f37a8853020fd7e8f09c63a54bf4a 100644 GIT binary patch delta 40107 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

6!W{ak{fZoi&e;OF5J@KW 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 delta 39929 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

6A#ns;bL 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 EdgeList { - let node_index = self.int_get_node_index(&node); - - EdgeList::from_vec(match node_index { - Some(node_index) => self - .int_iter_outgoing_edges(node_index) - .map(|edge| EdgeStruct::from_edge_ref(edge, self)) - .collect(), - None => Vec::new(), - }) + self.get_filtered_outgoing_edges(node, None) } - /// Get all outgoing edges from a node, filtered by edge type. + /// Get all outgoing edges from a node, filtered by edge type, in insertion + /// (document) order. pub fn get_filtered_outgoing_edges( &self, node: String, @@ -207,13 +200,20 @@ impl NoteGraph { let node_index = self.int_get_node_index(&node); EdgeList::from_vec(match node_index { - Some(node_index) => self - .int_iter_outgoing_edges(node_index) - .filter(|edge_ref| { - edge_matches_edge_filter_string(edge_ref.weight(), edge_types.as_ref()) - }) - .map(|edge| EdgeStruct::from_edge_ref(edge, self)) - .collect(), + Some(node_index) => { + let mut edges: Vec = self + .int_iter_outgoing_edges(node_index) + .filter(|edge_ref| { + edge_matches_edge_filter_string(edge_ref.weight(), edge_types.as_ref()) + }) + .map(|edge| EdgeStruct::from_edge_ref(edge, self)) + .collect(); + // petgraph prepends each new edge to the node's adjacency list, so + // iteration is newest-first. Reverse to restore insertion order, + // which is the order the builders read fields from the note (#790). + edges.reverse(); + edges + } None => Vec::new(), }) } diff --git a/wasm/tests/queries.rs b/wasm/tests/queries.rs index ad3730f7..10e1e9f6 100644 --- a/wasm/tests/queries.rs +++ b/wasm/tests/queries.rs @@ -270,6 +270,53 @@ fn test_get_filtered_outgoing_edges_selects_one_of_two_types() { assert_eq!(down_edges.edges.len(), 1); } +// ---- outgoing edge order (#790) ---- + +fn targets(g: &NoteGraph, edges: &[breadcrumbs_graph_wasm::data::edge_struct::EdgeStruct]) -> Vec { + edges.iter().map(|e| e.target_path(g).unwrap()).collect() +} + +/// `2026-W38` from #790: two `next` fields, in that order in the note. +fn week_graph() -> NoteGraph { + let mut g = NoteGraph::new(); + g.build_graph( + vec![node("W38"), node("2026-09"), node("W37"), node("W39"), node("My weeks")], + vec![ + edge("W38", "2026-09", "up"), + edge("W38", "W37", "prev"), + edge("W38", "W39", "next"), + edge("W38", "My weeks", "next"), + ], + vec![], + ) + .unwrap(); + g +} + +#[wasm_bindgen_test] +fn test_get_outgoing_edges_keeps_insertion_order() { + let g = week_graph(); + let edges = g.get_outgoing_edges("W38".to_owned()).edges; + assert_eq!(targets(&g, &edges), vec!["2026-09", "W37", "W39", "My weeks"]); +} + +#[wasm_bindgen_test] +fn test_get_filtered_outgoing_edges_keeps_insertion_order() { + let g = week_graph(); + let edges = g + .get_filtered_outgoing_edges("W38".to_owned(), Some(vec!["next".to_owned()])) + .edges; + assert_eq!(targets(&g, &edges), vec!["W39", "My weeks"]); +} + +#[wasm_bindgen_test] +fn test_get_filtered_grouped_outgoing_edges_keeps_insertion_order() { + let g = week_graph(); + let grouped = g.get_filtered_grouped_outgoing_edges("W38".to_owned(), None); + let next = grouped.get_edges("next").unwrap(); + assert_eq!(targets(&g, &next), vec!["W39", "My weeks"]); +} + // ---- edge_matches_edge_filter (Rc variant) ---- #[wasm_bindgen_test]