Files
cleveragents-core/features/diff_review.feature
T
2026-02-25 10:02:38 +00:00

264 lines
13 KiB
Gherkin

Feature: Diff review artifacts
As a developer reviewing plan changes
I want to build diff review artifacts from changesets
So that I can inspect changes before applying them
Background:
Given a plan ID "01PLAN000000000000000001"
And an empty changeset for the plan
Scenario: Empty changeset produces empty review artifact
When I build a review artifact from the changeset
Then the review artifact should have 0 total changes
And the review artifact should have 0 groups
And the review artifact should not be truncated
Scenario: Single CREATE change produces a diff entry
Given a change entry with operation "create" for path "src/main.py" in resource "RES001"
And after content for "src/main.py" is "print('hello')\n"
When I build a review artifact from the changeset
Then the review artifact should have 1 total changes
And the review artifact should have 1 groups
And group 0 should have 1 entries
And entry 0 in group 0 should have change type "create"
And entry 0 in group 0 should have path "src/main.py"
Scenario: MODIFY change generates unified diff
Given a change entry with operation "modify" for path "src/app.py" in resource "RES001"
And before content for "src/app.py" is "x = 1\ny = 2\n"
And after content for "src/app.py" is "x = 1\ny = 3\n"
When I build a review artifact from the changeset
Then entry 0 in group 0 should have change type "modify"
And the diff text in entry 0 of group 0 should contain "---"
And the diff text in entry 0 of group 0 should contain "+++"
Scenario: DELETE change entry
Given a change entry with operation "delete" for path "old.txt" in resource "RES001"
And before content for "old.txt" is "old content\n"
When I build a review artifact from the changeset
Then entry 0 in group 0 should have change type "delete"
And the diff text in entry 0 of group 0 should contain "---"
Scenario: Multiple changes across different resources
Given a change entry with operation "create" for path "a.py" in resource "RES001"
And a change entry with operation "modify" for path "b.py" in resource "RES002"
And after content for "a.py" is "new\n"
And before content for "b.py" is "old\n"
And after content for "b.py" is "new\n"
When I build a review artifact from the changeset
Then the review artifact should have 2 total changes
And the review artifact should have 2 groups
Scenario: Changes grouped by resource
Given a change entry with operation "create" for path "a.py" in resource "RES001"
And a change entry with operation "modify" for path "b.py" in resource "RES001"
And after content for "a.py" is "new\n"
And before content for "b.py" is "old\n"
And after content for "b.py" is "new\n"
When I build a review artifact from the changeset
Then the review artifact should have 1 groups
And group 0 should have 2 entries
Scenario: Binary file detection
Given a change entry with operation "create" for path "image.bin" in resource "RES001"
And after content for "image.bin" is "binary\x00data"
When I build a review artifact from the changeset
Then entry 0 in group 0 should be binary
And the diff text in entry 0 of group 0 should contain "[binary file]"
Scenario: Rename detection with matching content hash
Given a delete entry for path "old/file.py" in resource "RES001" with before_hash "abc123"
And a create entry for path "new/file.py" in resource "RES001" with after_hash "abc123"
When I build a review artifact from the changeset
Then the review artifact should have 1 groups
And group 0 should have 1 entries
And entry 0 in group 0 should be a rename
And entry 0 in group 0 rename should be from "old/file.py" to "new/file.py"
And group 0 should have 1 renamed
Scenario: Rename not detected when hashes differ
Given a delete entry for path "old/file.py" in resource "RES001" with before_hash "abc123"
And a create entry for path "new/file.py" in resource "RES001" with after_hash "xyz789"
When I build a review artifact from the changeset
Then group 0 should have 2 entries
And entry 0 in group 0 should not be a rename
Scenario: Max diff size truncation
Given a change entry with operation "create" for path "big.py" in resource "RES001"
And after content for "big.py" is a string of 100000 characters
When I build a review artifact with max diff size 100
Then the review artifact should be truncated
And entry 0 in group 0 should be truncated
Scenario: Stable ordering by resource then path
Given a change entry with operation "create" for path "z.py" in resource "RES002"
And a change entry with operation "create" for path "a.py" in resource "RES001"
And after content for "z.py" is "z\n"
And after content for "a.py" is "a\n"
When I build a review artifact from the changeset
Then group 0 should have resource id "RES001"
And group 1 should have resource id "RES002"
Scenario: Before and after content hashes in metadata
Given a hashed change entry "modify" path "f.py" resource "RES001" before_hash "hash1" after_hash "hash2"
And before content for "f.py" is "old\n"
And after content for "f.py" is "new\n"
When I build a review artifact from the changeset
Then entry 0 in group 0 should have before hash "hash1"
And entry 0 in group 0 should have after hash "hash2"
Scenario: File mode in metadata
Given a moded change entry "modify" path "script.sh" resource "RES001" after_mode 0o755
And before content for "script.sh" is "#!/bin/sh\n"
And after content for "script.sh" is "#!/bin/bash\n"
When I build a review artifact from the changeset
Then entry 0 in group 0 should have file mode 493
Scenario: Serialize to plain text
Given a change entry with operation "create" for path "new.py" in resource "RES001"
And after content for "new.py" is "hello\n"
And resource name "RES001" is "my-resource"
When I build a review artifact from the changeset
And I serialize the artifact to plain text
Then the plain text should contain "my-resource"
And the plain text should contain "new.py"
And the plain text should contain "Total changes: 1"
Scenario: Serialize to JSON
Given a change entry with operation "create" for path "new.py" in resource "RES001"
And after content for "new.py" is "hello\n"
When I build a review artifact from the changeset
And I serialize the artifact to JSON
Then the JSON output should be valid JSON
And the JSON output should contain key "total_changes"
And the JSON output should contain key "groups"
Scenario: Serialize to rich format
Given a change entry with operation "create" for path "new.py" in resource "RES001"
And after content for "new.py" is "hello\n"
When I build a review artifact from the changeset
And I serialize the artifact to rich format
Then the rich text should contain "[bold]"
And the rich text should contain "new.py"
Scenario: ResourceDiffGroup summary counts
Given a change entry with operation "create" for path "a.py" in resource "RES001"
And a change entry with operation "modify" for path "b.py" in resource "RES001"
And a change entry with operation "delete" for path "c.py" in resource "RES001"
And after content for "a.py" is "new\n"
And before content for "b.py" is "old\n"
And after content for "b.py" is "new\n"
And before content for "c.py" is "old\n"
When I build a review artifact from the changeset
Then group 0 should have 1 added
And group 0 should have 1 modified
And group 0 should have 1 deleted
Scenario: ReviewArtifact has plan and changeset IDs
When I build a review artifact from the changeset
Then the review artifact plan ID should match the changeset plan ID
And the review artifact changeset ID should match the changeset ID
Scenario: Empty content produces empty diff
Given a change entry with operation "modify" for path "empty.py" in resource "RES001"
When I build a review artifact from the changeset
Then the diff text in entry 0 of group 0 should be empty
Scenario: Multiple entries in same resource sorted by path
Given a change entry with operation "create" for path "z.py" in resource "RES001"
And a change entry with operation "create" for path "a.py" in resource "RES001"
And after content for "z.py" is "z\n"
And after content for "a.py" is "a\n"
When I build a review artifact from the changeset
Then entry 0 in group 0 should have path "a.py"
And entry 1 in group 0 should have path "z.py"
Scenario: Second entry fully truncated when budget exhausted
Given a change entry with operation "create" for path "a.py" in resource "RES001"
And a change entry with operation "create" for path "b.py" in resource "RES001"
And after content for "a.py" is a string of 1000 characters
And after content for "b.py" is a string of 1000 characters
When I build a review artifact with max diff size 50
Then the review artifact should be truncated
And entry 1 in group 0 should be truncated
And the diff text in entry 1 of group 0 should contain "[truncated]"
Scenario: JSON serialization includes hashes and file mode
Given a hashed change entry "modify" path "f.py" resource "RES001" before_hash "aaa" after_hash "bbb"
And a moded change entry "modify" path "g.py" resource "RES001" after_mode 0o644
And before content for "f.py" is "old\n"
And after content for "f.py" is "new\n"
And before content for "g.py" is "a\n"
And after content for "g.py" is "b\n"
When I build a review artifact from the changeset
And I serialize the artifact to JSON
Then the JSON output should be valid JSON
And the JSON output should have entry with before hash "aaa"
And the JSON output should have entry with after hash "bbb"
And the JSON output should have entry with file mode
Scenario: JSON serialization includes rename fields
Given a delete entry for path "old/r.py" in resource "RES001" with before_hash "h1"
And a create entry for path "new/r.py" in resource "RES001" with after_hash "h1"
When I build a review artifact from the changeset
And I serialize the artifact to JSON
Then the JSON output should be valid JSON
And the JSON output should have entry with rename from "old/r.py"
Scenario: Rich format shows truncation warning
Given a change entry with operation "create" for path "big.py" in resource "RES001"
And after content for "big.py" is a string of 100000 characters
When I build a review artifact with max diff size 100
And I serialize the artifact to rich format
Then the rich text should contain "[yellow]"
And the rich text should contain "truncated"
Scenario: Rich format shows binary marker
Given a change entry with operation "create" for path "bin.dat" in resource "RES001"
And after content for "bin.dat" is "binary\x00data"
When I build a review artifact from the changeset
And I serialize the artifact to rich format
Then the rich text should contain "[binary]"
Scenario: Rich format colorizes diff lines
Given a change entry with operation "modify" for path "c.py" in resource "RES001"
And before content for "c.py" is "old\n"
And after content for "c.py" is "new\n"
When I build a review artifact from the changeset
And I serialize the artifact to rich format
Then the rich text should contain "[green]"
And the rich text should contain "[red]"
Scenario: Cross-resource delete and create are not renamed
Given a delete entry for path "old/x.py" in resource "RES001" with before_hash "same"
And a create entry for path "new/x.py" in resource "RES002" with after_hash "same"
When I build a review artifact from the changeset
Then the review artifact should have 2 groups
And entry 0 in group 0 should not be a rename
And entry 0 in group 1 should not be a rename
Scenario: Multiple renames consume creates only once
Given a delete entry for path "old/a.py" in resource "RES001" with before_hash "h1"
And a delete entry for path "old/b.py" in resource "RES001" with before_hash "h1"
And a create entry for path "new/a.py" in resource "RES001" with after_hash "h1"
When I build a review artifact from the changeset
Then group 0 should have 2 entries
Scenario: Rename entry truncated when budget exhausted
Given a change entry with operation "create" for path "a.py" in resource "RES001"
And after content for "a.py" is a string of 1000 characters
And a delete entry for path "old/r.py" in resource "RES001" with before_hash "rh1"
And a create entry for path "new/r.py" in resource "RES001" with after_hash "rh1"
When I build a review artifact with max diff size 50
Then the review artifact should be truncated
And entry 1 in group 0 should be a rename
And entry 1 in group 0 should be truncated
And the diff text in entry 1 of group 0 should contain "[truncated]"
Scenario: Plain serialization shows binary marker
Given a change entry with operation "create" for path "img.png" in resource "RES001"
And after content for "img.png" is "png\x00header"
When I build a review artifact from the changeset
And I serialize the artifact to plain text
Then the plain text should contain "[binary file]"