Skip to content

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

Merged
Lucas1479 merged 1 commit into
Code-Amadeus:mainfrom
NopeCharon:fix/pin-submodule-patch-format
Nov 4, 2026
Merged

Lucas1479 merged 1 commit into
Code-Amadeus:mainfrom
NopeCharon:fix/pin-submodule-patch-format

Conversation

@NopeCharon

Copy link
Copy Markdown
Contributor

What and why

PATCH_FORMAT_ARGS keeps the user's diff configuration out of the patches parse_unified_diff reads, but diff.submodule still changed them when a submodule pointer moved (details in #287):

  • diff.submodule=log adds Submodule <path> a..b: and > subject lines. The parser appended each > ... line as context to the previous file's last hunk.
  • diff.submodule=diff emits the submodule's own file changes, which the canvas listed as attempt changes next to a hunk-less submodule entry.

This PR adds --submodule=short, Git's default, to PATCH_FORMAT_ARGS, so the submodule path shows its Subproject commit hunk regardless of configuration. Like the other options there, it overrides the setting for one command only. It applies to the committed and working-tree attempt patches and to collect_diff's patch.

Fixes #287

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 (PATCH_FORMAT_ARGS), used by server/work_artifact_registry.py for attempt patches.

User-visible effect, or none: for users with diff.submodule=log or diff, the attempt diff canvas no longer shows commit subjects as file content or submodule-internal files as attempt changes.

Compatibility or migration impact, or none: none. Patches persisted by earlier attempts are not rewritten.

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: 63 passed (Linux, Python 3.12, uv sync --locked --extra dev, Git 2.43).

  • The new test test_attempt_patch_ignores_user_submodule_diff_format (parametrized for log and diff; it finalizes an attempt that moves a real submodule and edits a file) fails on main and passes with this change.

  • python tests/test_work_artifact_registry.py: passed.

  • ruff check server tests/test_work_artifact_registry.py and git diff --check: passed.

  • pytest tests -k "diff or canvas or artifact": 182 passed, 18 skipped. The 6 failures are test_auip_artifact_style.py::test_real_entry_css_delivery_and_advisory_boundaries, which fails the same way on unmodified main in this environment.

  • Compared real git diff output for diff.submodule=short/log/diff (Git 2.54); --submodule=short produces the short output under all three settings.

  • 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

PATCH_FORMAT_ARGS keeps the user's diff configuration out of the patches
parse_unified_diff reads, but diff.submodule still changed them when a
submodule pointer moved:

- diff.submodule=log adds "Submodule <path> a..b:" and "  > subject"
  lines, which the parser appended as context to the previous file's
  last hunk.
- diff.submodule=diff emits the submodule's own file changes, which the
  canvas listed as attempt changes next to a hunk-less submodule entry.

Add --submodule=short, Git's default, so the submodule path shows its
"Subproject commit" hunk regardless of configuration. It applies to the
committed and working-tree attempt patches and to collect_diff's patch.

The new test finalizes an attempt that moves a real submodule and edits
a file, for both diff.submodule=log and diff.submodule=diff; it fails
without the fix.

Fixes Code-Amadeus#287
@NopeCharon
NopeCharon requested a review from Lucas1479 as a code owner November 4, 2026 08:21

@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 submodule-format fix and real-submodule regression coverage. I independently verified log and diff settings through provider.diff and both committed and working-tree attempt patches: the canvas consistently shows the submodule gitlink rather than commit prose or inner files. All 63 relevant Windows tests and all 15 hosted checks pass on this head. The fix belongs in the shared Host patch-format arguments and is ready to merge.

@Lucas1479
Lucas1479 merged commit 04b05c0 into Code-Amadeus:main Nov 4, 2026
15 checks passed
Lucas1479 added a commit that referenced this pull request Nov 4, 2026
## 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

- [x] 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 #289 and #290. After updating to merged main,
head `2f0c9488dd0938820d0f4331daeafe4cee1f1dc5` was verified
byte-for-byte identical to that tested tree.
- Test-file conflicts with #289/#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.

## Final check

- [x] One coherent blank-context preservation fix
- [x] No new dependency, schema, fallback or public configuration
- [x] No secrets, personal data 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 attempt patch follows the user's diff.submodule setting

2 participants