15dfda45a4
The apply_patch language documents `*** Add File` and `*** Move to` as strictly non-overwriting (create / rename), but the fs-level create and rename paths in applyNormalizedPatch wrote through to the resolved target without checking whether it already existed. Existing destinations were silently replaced, and in the rename case the source was also deleted. The multi-file executeApplyPatchPerFile aggregator caught each per-file exception, appended an error entry, and kept iterating. Later files still ran against an inconsistent post-state, and the aggregate result had no top-level isError — so a mixed partial application looked like a successful edit to the agent loop. Changes: - Add fs.exists guards before the create write and before the rename write/delete in packages/coding-agent/src/edit/modes/patch.ts. Both reject with ApplyPatchError before any side effect. - Make executeApplyPatchPerFile in packages/coding-agent/src/edit/index.ts stop at the first per-file failure, list applied vs. skipped files in the aggregate text, and propagate isError, matching executeSinglePathEntries. - Rename the two apply-patch scenario fixtures (010_move_..., 011_add_...) that pinned the buggy overwrite behavior to _rejects_ variants, and flip their expected/ trees so source and pre-existing destination remain byte-identical after the rejected apply. - Cover both failure modes with new regressions in packages/coding-agent/test/core/apply-patch.test.ts and a new packages/coding-agent/test/core/apply-patch-multi-file.test.ts. Fixes #4074
Overview
This directory is a collection of end to end tests for the apply-patch specification, meant to be easily portable to other languages or platforms.
Specification
Each test case is one directory, composed of input state (input/), the patch operation (patch.txt), and the expected final state (expected/). This structure is designed to keep tests simple (i.e. test exactly one patch at a time) while still providing enough flexibility to test any given operation across files.
Here's what this would look like for a simple test apply-patch test case to create a new file:
001_add/
input/
foo.md
expected/
foo.md
bar.md
patch.txt