# Understanding the Review Session Model in Tuicr: Architecture and Implementation

> Explore Tuicr's review session model architecture and implementation. Learn how this Rust structure tracks reviews, stores comments, and persists state for seamless code review resumption.

- Repository: [Almog Gavra/tuicr](https://github.com/agavra/tuicr)
- Tags: architecture
- Published: 2026-08-01

---

**Tuicr's review session model is a serializable Rust structure that tracks which files and hunks have been reviewed, stores file-level and line-level comments, and persists state to JSON for seamless resumption of code review sessions.**

The review session model in Tuicr serves as the central data structure that enables both interactive TUI and non-interactive CLI workflows. According to the agavra/tuicr source code, this model captures complete review state—from individual hunk approvals to session-wide metadata—in a robust, version-tolerant format defined in [`src/model/review.rs`](https://github.com/agavra/tuicr/blob/main/src/model/review.rs).

## Core Components of the Review Session Model

Tuicr implements its review session model through three primary types that work together to capture the complete state of a code review.

### FileReview: Per-File State Tracking

The `FileReview` struct manages review progress for individual files. Defined in [`src/model/review.rs`](https://github.com/agavra/tuicr/blob/main/src/model/review.rs) at lines 17-28, it tracks both aggregate and granular review status:

```rust
pub struct FileReview {
    pub path: PathBuf,                         // File location
    pub reviewed: bool,                        // Entire file marked reviewed
    pub status: FileStatus,                    // Added / Modified / Deleted
    pub file_comments: Vec<Comment>,           // Comments attached to file
    pub line_comments: HashMap<u32, Vec<Comment>>, // Line-specific comments
    pub reviewed_hunks: BTreeSet<String>,      // Hunk keys marked reviewed
    pub content_hash: Option<u64>,             // Hash for change detection
}

```

Key behaviors implemented for `FileReview` include:

- **`add_file_comment`** – Appends a comment to the entire file
- **`add_line_comment`** – Associates a comment with a specific line number
- **`toggle_hunk_reviewed`** – Flips the reviewed status of a specific hunk by adding or removing its key from `reviewed_hunks`
- **`comment_count`** – Returns the total number of comments for the file

### ReviewSession: Session-Wide Aggregation

The `ReviewSession` struct aggregates all `FileReview` instances and maintains metadata about the review context. Located in [`src/model/review.rs`](https://github.com/agavra/tuicr/blob/main/src/model/review.rs) at lines 89-123, it serves as the root container:

```rust
pub struct ReviewSession {
    pub id: String,                         // UUID of the session
    pub version: String,                    // Schema version
    pub repo_path: PathBuf,                 // Repository root
    pub branch_name: Option<String>,
    pub base_commit: String,                // Commit diff is based on
    pub diff_source: SessionDiffSource,     // Origin of the diff
    pub commit_range: Option<Vec<String>>,  // For commit-range diffs
    pub pr_session_key: Option<PrSessionKey>, // PR-specific identifier
    pub remote_comments_visibility: PrCommentsVisibility,
    pub commit_selection_range: Option<(usize, usize)>,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub review_comments: Vec<Comment>,      // Session-wide comments
    pub files: HashMap<PathBuf, FileReview>, // Per-file state
    pub session_notes: Option<String>,
}

```

The `ReviewSession` type provides several critical methods for managing the review lifecycle:

- **`new`** – Creates a fresh session with a generated UUID and timestamps
- **`add_file`** – Registers a file; automatically clears the `reviewed` flag if the file's `content_hash` changes (preventing stale reviews)
- **`add_diff_file`** – Adds a `DiffFile` from the VCS and prunes invalid hunk keys
- **`clear_comments`** – Removes comments with optional scope control via `ClearScope` enum
- **Query helpers** – `reviewed_count`, `has_reviewed_state`, `is_file_reviewed`, and `is_hunk_reviewed` support UI state rendering

### SessionDiffSource: Diff Origin Abstraction

Tuicr supports multiple diff sources through the `SessionDiffSource` enum (lines 66-87 in [`src/model/review.rs`](https://github.com/agavra/tuicr/blob/main/src/model/review.rs)), enabling the review session model to handle various Git workflows:

```rust
pub enum SessionDiffSource {
    WorkingTree,
    Staged,
    Unstaged,
    StagedAndUnstaged,
    CommitRange,
    WorkingTreeAndCommits,
    StagedUnstagedAndCommits,
    PullRequest,   // PR-mode sessions
    Pristine,      // Whole-repo annotation mode
}

```

## Persistence and Change Detection

The review session model implements automatic persistence to ensure review progress survives application restarts. Sessions serialize to JSON and store in `.local/share/tuicr/reviews/*.json`, with the [`persistence/storage.rs`](https://github.com/agavra/tuicr/blob/main/persistence/storage.rs) module handling atomic write operations.

A critical safety feature prevents stale approvals: when `add_file` detects that a file's `content_hash` differs from the stored hash, it automatically resets the `reviewed` flag. This ensures that modifications made after a review are not incorrectly marked as approved. The model also maintains forward compatibility through serde's default field handling, allowing legacy JSON files to load into newer schema versions.

## Working with the Review Session Model in Practice

The following example demonstrates creating a session, registering files, adding comments, and persisting state:

```rust
use tuicr::model::{review::ReviewSession, review::SessionDiffSource, comment::Comment, comment::CommentType};
use std::path::PathBuf;

// Create a new session for the working tree
let mut sess = ReviewSession::new(
    PathBuf::from("/my/repo"),
    "HEAD".to_string(),
    None,
    SessionDiffSource::WorkingTree,
);

// Register a file (normally done while parsing the diff)
let file_path = PathBuf::from("src/main.rs");
sess.add_file(file_path.clone(), tuicr::model::diff_types::FileStatus::Modified, 0xdeadbeef);

// Add a file-level comment
let comment = Comment::new(
    "Consider refactoring this module".into(),
    CommentType::from_id("suggestion"),
    None,
);
sess.files
    .get_mut(&file_path)
    .unwrap()
    .add_file_comment(comment);

// Add a line comment
let line_comment = Comment::new(
    "Potential off-by-one error".into(),
    CommentType::from_id("issue"),
    None,
);
sess.files
    .get_mut(&file_path)
    .unwrap()
    .add_line_comment(42, line_comment);

// Mark a specific hunk as reviewed
let hunk_key = "src/main.rs@@-10,1 +10,1@@".to_string();
sess.files
    .get_mut(&file_path)
    .unwrap()
    .toggle_hunk_reviewed(hunk_key);

// Persist the session (automatic in UI, manual here for demonstration)
tuicr::persistence::storage::save_session(&sess).expect("save failed");

```

## Summary

- **The review session model** in Tuicr centers on two main structures: `FileReview` for per-file state and `ReviewSession` for aggregate session management.
- **Granular tracking** supports both file-level and hunk-level review states, with line-specific comments stored in a `HashMap<u32, Vec<Comment>>`.
- **Change detection** uses content hashing to automatically invalidate reviews when files modify, preventing approval of outdated code.
- **Multi-source support** via `SessionDiffSource` enables reviews of working tree, staged, unstaged, commit ranges, and pull requests.
- **JSON persistence** in `.local/share/tuicr/reviews/` enables session resumption across TUI and CLI invocations.

## Frequently Asked Questions

### What data does the Tuicr review session model store?

The model stores session metadata (UUID, timestamps, repository path, base commit), per-file review states (reviewed flags, hunk keys, content hashes), and all comments (both file-level and line-level). It also tracks the diff source type and PR-specific identifiers when applicable, as defined in [`src/model/review.rs`](https://github.com/agavra/tuicr/blob/main/src/model/review.rs).

### How does Tuicr handle file changes during a review session?

When `ReviewSession::add_file` detects that a file's `content_hash` differs from the previously stored hash, it automatically clears the `reviewed` flag for that file. This ensures that modifications made after initial review are explicitly re-reviewed, preventing stale approvals from persisting.

### Where does Tuicr persist review session data?

Sessions serialize to JSON format and store in the `.local/share/tuicr/reviews/` directory, with each session saved as a separate `.json` file. The [`src/persistence/storage.rs`](https://github.com/agavra/tuicr/blob/main/src/persistence/storage.rs) module handles atomic serialization and deserialization using serde, ensuring data integrity across application restarts.

### Can the review session model handle different types of diffs?

Yes. The `SessionDiffSource` enum supports eight distinct diff origins including `WorkingTree`, `Staged`, `Unstaged`, `CommitRange`, and `PullRequest`. This allows the same review session model to manage everything from local uncommitted changes to multi-commit PR reviews.