Append a goal node (human prompt). Returns the new node's ID.
(&mut self, prompt: &str, timestamp: i64)
| 12 | /// |
| 13 | /// Returns the new node's ID. |
| 14 | pub fn append_goal(&mut self, prompt: &str, timestamp: i64) -> String { |
| 15 | let summary = truncate_prompt(prompt, MAX_GOAL_PROMPT_LEN); |
| 16 | let node = GraphNode::new(self.next_id(), NodeKind::Goal, timestamp, &summary); |
| 17 | let node_id = node.id.clone(); |
| 18 | |
| 19 | // Edge inference: chain goals sequentially |
| 20 | if let Some(ref prev_goal) = self.current_goal { |
| 21 | self.edges.push(GraphEdge::new( |
| 22 | prev_goal.clone(), |
| 23 | node_id.clone(), |
| 24 | EdgeKind::LedTo, |
| 25 | )); |
| 26 | self.stats.edge_count += 1; |
| 27 | } |
| 28 | |
| 29 | // If there was a pending human gate, the new goal resumes after it |
| 30 | if let Some(ref gate_id) = self.pending_human_gate.take() { |
| 31 | self.edges.push(GraphEdge::new( |
| 32 | gate_id.clone(), |
| 33 | node_id.clone(), |
| 34 | EdgeKind::ResumedAfter, |
| 35 | )); |
| 36 | self.stats.edge_count += 1; |
| 37 | } |
| 38 | |
| 39 | // Reset cursor state for new goal |
| 40 | self.current_goal = Some(node_id.clone()); |
| 41 | self.pending_explorations.clear(); |
| 42 | self.last_commitment = None; |
| 43 | |
| 44 | self.push_node(node); |
| 45 | node_id |
| 46 | } |
| 47 | |
| 48 | /// Append a tool call node, classified by the rule-based classifier. |
| 49 | /// |