ISSUES CLOSED: #303
2.9 KiB
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.
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
SequenceMatcherpath 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 outputto_json(artifact)— structured JSON for programmatic useto_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 |