Remove derived turn/todo KG state before a session ledger is re-numbered. Edges not owned by the session index are returned with their turn endpoints remapped so callers can restore them afterward.
(
&mut self,
old_turns: &[SessionTurn],
new_turns: &[SessionTurn],
)
| 103 | /// re-numbered. Edges not owned by the session index are returned with |
| 104 | /// their turn endpoints remapped so callers can restore them afterward. |
| 105 | pub(crate) fn clear_session_turn_kg( |
| 106 | &mut self, |
| 107 | old_turns: &[SessionTurn], |
| 108 | new_turns: &[SessionTurn], |
| 109 | ) -> PristineResult<Vec<KgEdge>> { |
| 110 | let mut todo_ids = std::collections::BTreeSet::new(); |
| 111 | let old_turn_ids: std::collections::BTreeSet<String> = old_turns |
| 112 | .iter() |
| 113 | .map(|turn| turn_node_id(&turn.session_id, turn.turn_number)) |
| 114 | .collect(); |
| 115 | let new_turn_ids: std::collections::HashMap<Hash, String> = new_turns |
| 116 | .iter() |
| 117 | .map(|turn| { |
| 118 | ( |
| 119 | turn.provenance_hash, |
| 120 | turn_node_id(&turn.session_id, turn.turn_number), |
| 121 | ) |
| 122 | }) |
| 123 | .collect(); |
| 124 | let mut remapped_turn_ids = std::collections::HashMap::new(); |
| 125 | let mut preserved = std::collections::BTreeMap::new(); |
| 126 | |
| 127 | for turn in old_turns { |
| 128 | let old_turn_id = turn_node_id(&turn.session_id, turn.turn_number); |
| 129 | if let Some(new_turn_id) = new_turn_ids.get(&turn.provenance_hash) { |
| 130 | remapped_turn_ids.insert(old_turn_id.clone(), new_turn_id.clone()); |
| 131 | } |
| 132 | for todo in &turn.todos { |
| 133 | // Current namespaced form. |
| 134 | todo_ids.insert(todo_node_id(&turn.session_id, &todo.id)); |
| 135 | // Pre-fix global form, for safe migration during a rewrite. |
| 136 | todo_ids.insert(legacy_todo_node_id(&todo.id)); |
| 137 | } |
| 138 | |
| 139 | let edges = self |
| 140 | .get_kg_edges_from(&old_turn_id)? |
| 141 | .into_iter() |
| 142 | .chain(self.get_kg_edges_to(&old_turn_id)?); |
| 143 | for edge in edges { |
| 144 | if !is_session_owned_turn_edge(&edge, turn) { |
| 145 | preserved.insert( |
| 146 | (edge.from_id.clone(), edge.to_id.clone(), edge.kind.clone()), |
| 147 | edge, |
| 148 | ); |
| 149 | } |
| 150 | } |
| 151 | } |
| 152 | |
| 153 | for turn_id in &old_turn_ids { |
| 154 | self.del_kg_node(turn_id)?; |
| 155 | } |
| 156 | |
| 157 | for todo_id in todo_ids { |
| 158 | let is_session_todo = self |
| 159 | .get_kg_node(&todo_id)? |
| 160 | .is_some_and(|node| node.kind == "todo" && node.source == "session_ledger"); |
| 161 | if is_session_todo |
| 162 | && self.get_kg_edges_from(&todo_id)?.is_empty() |
no test coverage detected