# Diff Review The diff review module builds reviewable diff artifacts from `SpecChangeSet` records, grouping changes by resource and producing unified diff text for CLI display. ## Overview When a plan accumulates changes through tool executions, the diff review system transforms the raw `ChangeEntry` records into a structured `ReviewArtifact` suitable for human review before applying changes. ## Domain Models ### DiffEntry A single diff entry for CLI review. Contains: | Field | Type | Description | |---|---|---| | `resource_id` | `str` | Resource ULID | | `resource_name` | `str` | Human-readable resource name | | `path` | `str` | File path | | `change_type` | `str` | Operation type (create/modify/delete/rename) | | `before_content` | `str \| None` | Content before the change | | `after_content` | `str \| None` | Content after the change | | `before_hash` | `str \| None` | SHA-256 before | | `after_hash` | `str \| None` | SHA-256 after | | `file_mode` | `int \| None` | File permission mode | | `is_binary` | `bool` | Whether the file is binary | | `is_rename` | `bool` | Whether this is a rename/move | | `rename_from` | `str \| None` | Original path for renames | | `rename_to` | `str \| None` | Destination path for renames | | `diff_text` | `str` | Unified diff text | | `truncated` | `bool` | Whether the diff text was truncated | ### ResourceDiffGroup Groups diff entries for a single resource. Provides summary counts via properties: `added`, `modified`, `deleted`, `renamed`. ### ReviewArtifact Complete diff review artifact for a plan. Contains grouped diff entries, total change count, and truncation status. ## DiffBuilder `DiffBuilder` takes a `SpecChangeSet` and optional content maps to produce a `ReviewArtifact`. ```python from cleveragents.domain.models.core.diff_review import DiffBuilder builder = DiffBuilder(max_diff_size=50_000, context_lines=3) artifact = builder.build( changeset, before_contents={"src/main.py": "old content"}, after_contents={"src/main.py": "new content"}, resource_names={"RES001": "my-resource"}, ) ``` ### Features - **Unified diff generation** using `difflib.unified_diff` - **Binary detection** via null byte checking - **Rename detection** using `SequenceMatcher` path similarity (>0.6) combined with matching content hashes - **Truncation** when total diff text exceeds `max_diff_size` (applies uniformly to all entry types including renames) - **Stable ordering** by resource ID, then path within each group ## DiffSerializer Renders a `ReviewArtifact` to various output formats: - `to_plain(artifact)` — plain text for terminal output - `to_json(artifact)` — structured JSON for programmatic use - `to_rich(artifact)` — rich markup with `[bold]`, `[green]`, `[red]` tags ## Constants | Name | Default | Description | |---|---|---| | `DEFAULT_MAX_DIFF_SIZE` | 50,000 | Maximum total diff text characters | | `RENAME_SIMILARITY_THRESHOLD` | 0.6 | Minimum path similarity for rename detection |