Skip to content

fix(work): preserve blank context throughout attempt diffs - #288

Merged
Lucas1479 merged 7 commits into
Code-Amadeus:mainfrom
NopeCharon:fix/unified-diff-blank-context
Nov 4, 2026
Merged

Lucas1479 merged 7 commits into
Code-Amadeus:mainfrom
NopeCharon:fix/unified-diff-blank-context

Conversation

@NopeCharon

@NopeCharon NopeCharon commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

What and why

Fixes #285. With diff.suppressBlankEmpty=true, Git emits blank context as empty patch lines. The parser previously discarded these lines, omitting context and shifting later line numbers.

The parser now accepts empty lines while the hunk still expects content. Host patch assembly also removes only one final LF from each patch segment, rather than stripping every trailing LF. This preserves blank context at the end of committed and working-tree patches, including when both are combined. Empty separators outside completed hunks remain ignored.

Owning layers: server/unified_diff.py and collect_git_delta in server/work_artifact_registry.py. The output schema, configuration, permissions and attribution rules are unchanged.

Change class

  • Routine bug fix and regression coverage
  • Product-semantic or public-contract change
  • Isolated experiment

Evidence

  • The original parser and real-repository regressions fail on unmodified main and pass with the parser fix.

  • Six additional end-to-end cases cover one/two trailing blank context lines in working-only, committed-only and combined patches. All six fail before the assembly fix and pass afterward.

  • python -X utf8 -m pytest tests/test_local_git_provider_diff.py tests/test_work_artifact_registry.py tests/test_unified_diff_canvas.py tests/test_work_export_integration.py -q: 73 passed on the final combined tree, including fix(work): read copy headers in the attempt diff canvas #289 and fix(work): pin the submodule format of patches the Host parses #290. After updating to merged main, head 880d7496696122cb467bbe271fd6918e64d74479 was verified byte-for-byte identical to that tested tree.

  • Test-file conflicts with fix(work): read copy headers in the attempt diff canvas #289/fix(work): pin the submodule format of patches the Host parses #290 were resolved by retaining both sides' test functions and manual runner calls. Existing test bodies were checked unchanged.

  • Ruff on the affected files and git diff --check: passed.

  • Local validation used Windows, Python 3.12.10 and Git 2.56.0. Linux/macOS and broader application validation rely on hosted CI; no local Electron journey or live provider call was performed.

  • All 15 hosted checks passed on head 880d7496696122cb467bbe271fd6918e64d74479, including source/packaged Electron smoke and catalog publication/recovery. Merged main e90364362e19c0db063d94fef042b0243f584cb3 was verified identical to the tested tree.

Final check

  • One coherent blank-context preservation fix
  • No new dependency, schema, fallback or public configuration
  • No secrets, personal data or restricted assets
  • CPU/model-less baseline retained

With diff.suppressBlankEmpty=true, git diff writes a blank context line
as an empty line instead of a single space. Git apply and GNU patch read
that line as context, but parse_unified_diff skipped every empty line.
The Work attempt diff canvas therefore dropped blank context lines and
numbered every following line of the hunk too low.

Read an empty line as blank context while the hunk header still expects
old or new lines. Empty lines outside a hunk body, such as the one after
the patch's final newline, are still ignored. No command-line option
overrides diff.suppressBlankEmpty, so the parser is the layer that has
to accept both forms.

Tests cover the parser directly and an attempt finalized in a real
repository with diff.suppressBlankEmpty set; both fail without the fix.

Fixes Code-Amadeus#285
With diff.renames=copies, git diff reports a new file copied from a
changed file with "copy from" / "copy to" extended headers. The parser
handled the equivalent rename headers but ignored these, so a copy was
shown as "modified". An exact copy has no ---/+++ lines; when its source
and target paths contain spaces the diff --git header cannot be split,
so the canvas showed a phantom entry plus the real path again as a
hunk-less entry from changed_files.

Read the copy headers like the rename headers: the entry gets status
"copied", oldPath from "copy from", and path/newPath from "copy to".
The status is displayed as text by the canvas; no consumer branches on
its value.

Tests cover exact and edited copies in the parser and a committed copy
in an attempt finalized with diff.renames=copies; both fail without the
fix.

Fixes Code-Amadeus#286
@NopeCharon
NopeCharon requested a review from Lucas1479 as a code owner November 4, 2026 08:21
# Conflicts:
#	tests/test_work_artifact_registry.py
# Conflicts:
#	tests/test_unified_diff_canvas.py
#	tests/test_work_artifact_registry.py
# Conflicts:
#	tests/test_unified_diff_canvas.py
#	tests/test_work_artifact_registry.py
@Lucas1479 Lucas1479 changed the title fix(work): keep blank context lines in the attempt diff canvas fix(work): preserve blank context throughout attempt diffs Nov 4, 2026
@Lucas1479

Copy link
Copy Markdown
Member

Thank you for the parser fix and the real-Git regression. I completed the same invariant in Host patch assembly: only one final LF is removed from each segment, preserving trailing blank context. Six added end-to-end cases cover one/two blank context lines in working-only, committed-only and combined patches; all six failed before this one-line fix. Test conflicts were resolved with both sides retained. The final composition with #289 and #290 passes 73 tests plus Ruff, and the latest-main update preserves the exact tested tree. The completed head is 2f0c9488dd0938820d0f4331daeafe4cee1f1dc5; hosted CI is the remaining merge gate.

@Lucas1479
Lucas1479 merged commit e903643 into Code-Amadeus:main Nov 4, 2026
15 checks passed
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.

Work diff canvas drops blank context lines when the user's Git config sets diff.suppressBlankEmpty

2 participants