Skip to content

fix(work): pin the format of patches the Host parses - #284

Merged
Lucas1479 merged 1 commit into
Code-Amadeus:mainfrom
NopeCharon:fix/git-diff-config-independent
Nov 3, 2026
Merged

Lucas1479 merged 1 commit into
Code-Amadeus:mainfrom
NopeCharon:fix/git-diff-config-independent

Conversation

@NopeCharon

Copy link
Copy Markdown
Contributor

What and why

collect_git_delta and collect_diff ran plain git diff, so the user's own diff configuration decided the format of the patch that parse_unified_diff renders in the Work attempt diff canvas, and that the Work page shows as raw text (details in #279):

  • diff.mnemonicPrefix=true turns git diff HEAD prefixes into c/ / w/. The canvas names the file w/app.py and lists the real path again as a hunk-less "modified" entry.
  • color.diff=always wraps every line in ANSI escapes. No header or hunk is recognised, so every file shows 0 additions and 0 deletions.
  • diff.noprefix=true drops the a/ / b/ prefixes.
  • diff.external replaced collect_diff's patch. Unlike the attempt delta, collect_diff did not pass --no-ext-diff.

This PR adds PATCH_FORMAT_ARGS (--no-ext-diff --no-color --src-prefix=a/ --dst-prefix=b/) to server/local_git.py and uses it for the committed and working-tree attempt patches and for collect_diff's patch. The options override the configuration for one command only, so the user's Git setup is left untouched. --name-only, -z and porcelain status calls are not affected by these settings and are unchanged.

Fixes #279

Linked Issue for product-semantic or public-contract changes: none (routine fix)

Change class

  • Routine fix, documentation, test, maintenance, or presentation-only UI
  • Product-semantic or public-contract change discussed in the linked Issue
  • Isolated, default-off experiment

Owning layer: server/local_git.py, the Host helper that runs Git for machine consumers, and its callers in server/work_artifact_registry.py, which produce the attempt patch.

User-visible effect, or none: users with those Git settings see the correct files, hunks and counts in the attempt diff canvas, and a readable raw patch.

Compatibility or migration impact, or none: none. Patches persisted by earlier attempts are not rewritten. New attempts store the standard a/ / b/ format that the parser already expects.

Evidence

Commands and manual journeys run:

  • python -m pytest -q 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: 48 passed (Linux, uv sync --locked --extra dev).

  • The new tests test_attempt_patch_ignores_user_diff_format_config (parametrized for diff.mnemonicPrefix, diff.noprefix and color.diff=always, covering committed and working-tree patches through parse_unified_diff) and test_provider_diff_patch_ignores_user_diff_format_config fail on main and pass with this change.

  • python -m ruff check server and the changed test files: passed.

  • Full pytest tests on Linux (VN overlay tests needing tkinter excluded): 6115 passed, 84 failed. Re-running the failing files on unmodified main gives the same failures (ACP/Codex SDK, AUIP entry boot, Windows-only wallpaper and desktop tests), except two test_codex_approval_cancel.py cases that were timing-flaky under load; that file passes 14/14 on both branches when run alone.

  • Relevant Python tests pass

  • CPU/model-less baseline remains supported

  • Electron npm run build passes when Electron code changed

  • Dependency audit passes when dependencies changed

  • Before/after screenshots are attached for visible UI changes

  • Documentation/examples are updated for changed settings or contracts

Final check

  • This PR addresses one coherent problem without unrelated cleanup
  • It does not add a speculative API, fallback, or compatibility path
  • No secrets, local state, model weights, voice material, or restricted assets are included
  • Third-party notices and provenance are preserved

collect_git_delta and collect_diff run plain `git diff`, so the user's
diff configuration decides the shape of the patch that
parse_unified_diff renders in the Work attempt diff canvas and that the
Work page shows as raw text:

- diff.mnemonicPrefix=true turns `git diff HEAD` prefixes into c/ and
  w/, so the canvas names the file "w/app.py" and lists the real path a
  second time as a hunk-less "modified" entry;
- color.diff=always wraps every line in ANSI escapes, so no header or
  hunk is recognised and every file shows 0 additions and 0 deletions;
- diff.noprefix=true drops the a/ and b/ prefixes;
- diff.external replaced collect_diff's patch, which, unlike the
  attempt delta, did not pass --no-ext-diff.

Add PATCH_FORMAT_ARGS (--no-ext-diff, --no-color, --src-prefix=a/,
--dst-prefix=b/) to server/local_git.py and use it for the committed
and working-tree attempt patches and for collect_diff's patch. These
options override the configuration for one command only, so the user's
Git setup is left untouched.

Fixes Code-Amadeus#279
@NopeCharon
NopeCharon requested a review from Lucas1479 as a code owner November 2, 2026 13:01

@Lucas1479 Lucas1479 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the focused fix and regression coverage. The shared patch-format arguments repair the four configurations reported in #279 at the Host Git-output boundary without changing user configuration. I independently checked real Git output for prefix/color handling and the external-driver boundary. All 15 hosted checks pass on this head. Additional submodule/copy/blank-context configurations are separate pre-existing follow-ups and do not block this scoped fix.

@Lucas1479
Lucas1479 merged commit 422ffd4 into Code-Amadeus:main Nov 3, 2026
15 checks passed
Lucas1479 added a commit that referenced this pull request Nov 3, 2026
## What and why

Fixes #281. Git patch lines are delimited by LF. Python's `splitlines()`
also splits form feeds, vertical tabs and Unicode separators that belong
inside a source line, producing truncated text, phantom changes and
incorrect line numbers in the Work diff canvas.

The parser now splits only on LF and retains its existing CRLF display
handling. The Host's new-file patch generator uses the same LF framing,
preserves empty/trailing blank lines and emits the missing-final-newline
marker based on LF. Final Git-delta assembly no longer strips source
whitespace from the last patch line.

Owning layers: `server/unified_diff.py` and
`server/work_artifact_registry.py`. Existing output schemas, permissions
and attribution rules are unchanged. The generator is shared by
Git-untracked files and new files in non-Git workspaces.

## Change class

- [x] Routine bug fix with regression coverage
- [ ] Product-semantic or public-contract change
- [ ] Isolated experiment

## Evidence

- The author's parser regression and real Git examples demonstrate the
original count/text corruption.
- Eight generator-to-parser cases cover embedded separators, other
control characters, empty files, blank/trailing blank lines, CRLF,
missing final LF and bare CR.
- Three end-to-end attempt cases cover Git-tracked, Git-untracked and
filesystem-new files, including trailing form-feed/space preservation.
- New regressions were observed failing before their corresponding
fixes.
- On Windows/Python 3.12.10, `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`: **61 passed** on head
`9b8bbe869901b53ca707eb1486a721b0218d1ade`, including merged #284 and
#282.
- Ruff on all four changed files and `git diff --check`: passed.
- No live provider calls or local Electron journey were needed for this
parser/generator change; hosted checks cover the broader application.

## Final check

- [x] One coherent content-preservation fix
- [x] No new dependency, schema, fallback or public configuration
- [x] No secrets, personal state or restricted assets
- [x] CPU/model-less baseline retained

---------

Co-authored-by: Lucas1479 <sli776@aucklanduni.ac.nz>
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 breaks when the user's Git config sets diff.mnemonicPrefix, color.diff=always or diff.noprefix

2 participants