Skip to content

diff: render a supplied unified diff, and wire codex file changes to it - #5

Merged
tdwd merged 1 commit into
mainfrom
codex-diffs
Sep 7, 2026
Merged

diff: render a supplied unified diff, and wire codex file changes to it#5
tdwd merged 1 commit into
mainfrom
codex-diffs

Conversation

@tdwd

@tdwd tdwd commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

codex reports an edit as a ready-made unified hunk and never sends the whole file, so there was no before/after pair to build a fileDiff from.

That looked like a design problem. It was not one: both renderers already worked from unified text. diff.go and diff_split.go each called udiff.Unified(old, new) on their first line and spent the rest of the function parsing the result back to style it. Computing it was only ever step one.

So they now take the unified text and style it, and fileDiff.unifiedText() is the single place that decides whether to use a supplied diff or compute one. No reconstruction, no second renderer, both diff styles working on both backends.

Behaviour-preserving for claude

The same string reaches the same styling loop. The existing renderer tests pass unchanged, which is the check that matters here.

The three codex change kinds

All confirmed against the live CLI, because they put different things in the same diff field:

kind diff holds maps to
add the new file's content new
delete the removed file's content old
update a unified hunk unified

Reading that wrong renders a deletion as an addition.

One bug a live test caught

Display paths are trimmed against the working root the agent reported on thread/started, not os.Getwd. Those are equal by convention in production, so the difference is invisible — until a live test rooted in a temp dir rendered the full absolute path across two wrapped lines.

Verified

go vet, full suite, and CATHODE_CODEX_LIVE=1 driving a real edit end to end:

╔════════════════════════════════════════════╗
║  target.txt  +1 -1                         ║
║         │ @@ -1,3 +1,3 @@                  ║
║   1    1│   line one                       ║
║   2     │ - line two                       ║
║        2│ + line TWO                       ║
║   3    3│   line three                     ║
╚════════════════════════════════════════════╝

The new test is discriminating: removing the diff path fails it.

Not verified: the TUI under -backend codex.

codex reports an edit as a ready-made unified hunk and never sends the whole
file, so there was no before/after pair to build a fileDiff from. That looked
like a design problem and was not one: both renderers already worked FROM
unified text. Each computed it on its first line and spent the rest of the
function parsing it back.

So they now take the unified text and style it, and fileDiff.unifiedText is the
one place that decides whether to use a supplied diff or compute one. No
reconstruction, no second renderer, and both diff styles work on both backends.

Behaviour-preserving for claude: the same string reaches the same styling loop,
and the existing renderer tests pass unchanged.

The three codex change kinds put different things in the same `diff` field, all
confirmed against the live CLI: add and delete carry the file's content, update
carries the hunk. Reading that wrong renders a deletion as an addition.

Display paths are trimmed against the working root the agent reported on
thread/started, not os.Getwd. Those are equal by convention only, and a live
test rooted in a temp dir rendered the full absolute path until this was fixed
— the kind of assumption that stays invisible in production.
@tdwd
tdwd merged commit 34d31dd into main Sep 7, 2026
1 check passed
@tdwd
tdwd deleted the codex-diffs branch September 7, 2026 19:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant