Index an immutable provenance graph as the next turn of its session. The session ID is the portable external identity. The turn key uses the full BLAKE3 namespace only for local ordering; the serialized value retains the original session ID so the index is self-describing.
(
&mut self,
session_id: &str,
json_path: &str,
provenance_hash: &Hash,
graph: &crate::change::ProvenanceGraph,
)
| 544 | /// full BLAKE3 namespace only for local ordering; the serialized value |
| 545 | /// retains the original session ID so the index is self-describing. |
| 546 | pub fn index_session_turn( |
| 547 | &mut self, |
| 548 | session_id: &str, |
| 549 | json_path: &str, |
| 550 | provenance_hash: &Hash, |
| 551 | graph: &crate::change::ProvenanceGraph, |
| 552 | ) -> PristineResult<()> { |
| 553 | use crate::change::session::{SessionRecord, SessionTurn}; |
| 554 | |
| 555 | // Idempotency is session-local because forked sessions legitimately |
| 556 | // share provenance hashes. |
| 557 | let turns = self.load_session_turns_for_write(session_id)?; |
| 558 | if turns |
| 559 | .iter() |
| 560 | .any(|turn| turn.provenance_hash == *provenance_hash) |
| 561 | { |
| 562 | return Ok(()); |
| 563 | } |
| 564 | |
| 565 | let mut record = self |
| 566 | .load_session_record_for_write(session_id)? |
| 567 | .unwrap_or_else(|| SessionRecord { |
| 568 | session_id: session_id.to_string(), |
| 569 | json_path: json_path.to_string(), |
| 570 | view_name: None, |
| 571 | parent_view: None, |
| 572 | first_provenance: None, |
| 573 | latest_provenance: None, |
| 574 | turn_count: 0, |
| 575 | started_at: graph.timestamp, |
| 576 | ended_at: None, |
| 577 | }); |
| 578 | |
| 579 | if record.json_path.is_empty() { |
| 580 | record.json_path = json_path.to_string(); |
| 581 | } |
| 582 | |
| 583 | let candidate = SessionTurn { |
| 584 | session_id: session_id.to_string(), |
| 585 | // Canonical numbering is assigned from the complete turn set. |
| 586 | turn_number: 0, |
| 587 | goal: graph |
| 588 | .nodes |
| 589 | .iter() |
| 590 | .find(|node| { |
| 591 | matches!( |
| 592 | node.kind, |
| 593 | crate::change::provenance_graph::ProvenanceNodeKind::Goal |
| 594 | ) |
| 595 | }) |
| 596 | .map(|node| node.summary.clone()), |
| 597 | provenance_hash: *provenance_hash, |
| 598 | change_hashes: graph.changes_explained.clone(), |
| 599 | previous_provenance: graph.previous, |
| 600 | timestamp: graph.timestamp, |
| 601 | plan_id: graph.plan_id.clone(), |
| 602 | todos: graph.todos.clone(), |
| 603 | }; |
no test coverage detected