Files
codex/codex-rs/guardian-context/src/cursor.rs
T
felixxia-oai b3e0c49dfb Extract guardian transcript selection into guardian-context (#45417)
## What changed

Move full/delta transcript selection into the shared `TranscriptMode::select` API and use it when building guardian prompts. Export `TranscriptCursor`, `TranscriptMode`, and `TranscriptSelection` from `codex-guardian-context`.

Preserve full-transcript fallback when the history version changes or the saved cursor exceeds the collected entry count. Select entries before profile retention, preserving their numbering and returning a proposed cursor that counts all collected entries. Hosts remain responsible for committing and invalidating cursors.

## Testing

Add a regression test verifying that sliding-window retention preserves the collected-entry cursor and that an appended entry is selected and numbered correctly in the next delta.

GitOrigin-RevId: a2192c08e23c18302b0105ba47aeb2780eb4a015
2026-09-14 12:52:16 +00:00

61 lines
2.1 KiB
Rust

//! Selects full or incremental review evidence before profile retention.
//! Selection only proposes the next cursor; callers commit it with reviewed history.
//! Hosts must invalidate cursors when collection settings or history offsets change.
use crate::ConversationTranscriptEntry;
/// End of the collected transcript in one host-owned review-history generation.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct TranscriptCursor {
pub parent_history_version: u64,
pub transcript_entry_count: usize,
}
/// Whether to start a transcript or continue from previously reviewed evidence.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum TranscriptMode {
Full,
Delta { cursor: TranscriptCursor },
}
/// Selected evidence and its original numbering, before rendering or admission.
pub enum TranscriptSelection<'a> {
Full(&'a [ConversationTranscriptEntry]),
Delta {
entries: &'a [ConversationTranscriptEntry],
offset: usize,
},
}
impl TranscriptMode {
/// Falls back to full evidence if the saved cursor no longer addresses this history.
/// The returned cursor counts collected entries, including any later omitted by a profile.
pub fn select(
self,
entries: &[ConversationTranscriptEntry],
parent_history_version: u64,
) -> (TranscriptSelection<'_>, TranscriptCursor) {
let next_cursor = TranscriptCursor {
parent_history_version,
transcript_entry_count: entries.len(),
};
let selection = match self {
Self::Delta { cursor }
if cursor.parent_history_version == parent_history_version
&& cursor.transcript_entry_count <= entries.len() =>
{
TranscriptSelection::Delta {
entries: &entries[cursor.transcript_entry_count..],
offset: cursor.transcript_entry_count,
}
}
Self::Full | Self::Delta { .. } => TranscriptSelection::Full(entries),
};
(selection, next_cursor)
}
}
#[cfg(test)]
#[path = "cursor_tests.rs"]
mod tests;