## Why
Updating a file with `apply_patch` historically normalized its contents to LF,
which can rewrite line endings outside the requested change.
## What changed
- Add an opt-in `PreserveLineEndings` update mode and thread it through patch
verification, application, and the standalone executable. Existing APIs keep
the LF-normalizing mode by default.
- Retain the original endings of untouched and context lines, including in
mixed-ending files, and use the file's first line ending for inserted or
replaced lines.
- Track patch context separately from identical changed lines so preservation
does not alter replacement ordering or matching.
## Testing
Add coverage for CRLF, CR, mixed endings, trailing blank lines, repeated lines,
EOF overlap rejection, and legacy LF normalization.
GitOrigin-RevId: 085f0cbc57e0965aa62c6a2d0e80870424e762f5
## Why
`apply_patch` maintained separate batch and streaming parsers for the
same patch grammar. That duplicated the parsing rules and allowed final
execution to disagree with the live streamed preview.
## What changed
- Make `StreamingPatchParser` the single owner of hunk and environment
ID parsing.
- Keep heredoc and outer patch-boundary normalization in the existing
`parse_patch` wrapper, preserving its public API.
- Reject non-whitespace content after `*** End Patch` and preserve
separator handling after `*** End of File`.
- Reject duplicate environment ID preambles explicitly.
- Remove the duplicate batch hunk parser and its implementation-specific
tests.
The change removes 201 net lines while retaining focused coverage for
the unified parser's boundary behavior.
## Validation
- `just test -p codex-apply-patch`
- Compared a 24-hour corpus of 2,788,059 observed `apply_patch` payloads
against the previous batch parser. All 2,779,502 accepted payloads
produced identical hunks, canonical patch text, and environment IDs; the
remaining 8,557 payloads were rejected by both parsers, with zero
acceptance or payload mismatches.
## Summary
- add multi-environment apply_patch routing for both freeform and
function-call tool flows
- parse and reconcile the optional environment selector in the main
apply_patch parser, then verify against the selected environment in the
handler
- carry environment_id through runtime and approval surfaces so
remote-targeted patches stay explicit end to end
## Testing
- just fmt
- remote exec-server e2e: `cargo test -p codex-core --test all
apply_patch_multi_environment_uses_remote_executor -- --nocapture` on
dev via `scripts/test-remote-env.sh`
---------
Co-authored-by: Codex <noreply@openai.com>