Summary
strip_conflict_markers_keep_ours in src/authorship/virtual_attribution.rs:2111-2134 uses content.lines() (which strips both \n and \r\n) then rejoins with result.join("\n") (LF only). On Windows, working-tree files with CRLF endings are silently normalized to LF. The returned string is then passed as final_state to merge_attributions_favoring_first, where attribution diffing operates on byte offsets — but the stashed VA's byte offsets were computed against the original CRLF content, causing misalignment.
Affected code
src/authorship/virtual_attribution.rs:2128:
let mut out = result.join("\n"); // always LF, even if input was CRLF
Impact
Windows only. If a user has CRLF-ending files and runs checkout/switch --merge that produces conflicts, the conflict-marker stripping silently converts line endings, causing byte-offset drift between the cleaned content and the stashed VA. The result is degraded/misaligned attribution rather than a crash.
Notes
- Not reproducible in CI:
GIT_CONFIG_NOSYSTEM=1 suppresses core.autocrlf, and Windows CI tests were already failing for unrelated reasons before this PR.
- The project's POSIX-normalization convention (paths use forward slashes per AGENTS.md) suggests LF-normalization of content may be intentional or at least acceptable.
- Fix would be to detect CRLF input and rejoin with
\r\n, or to normalize the stashed VA content to LF before computing offsets so both sides agree.
Discovered via Devin PR review on #959.
Summary
strip_conflict_markers_keep_oursinsrc/authorship/virtual_attribution.rs:2111-2134usescontent.lines()(which strips both\nand\r\n) then rejoins withresult.join("\n")(LF only). On Windows, working-tree files with CRLF endings are silently normalized to LF. The returned string is then passed asfinal_statetomerge_attributions_favoring_first, where attribution diffing operates on byte offsets — but the stashed VA's byte offsets were computed against the original CRLF content, causing misalignment.Affected code
src/authorship/virtual_attribution.rs:2128:Impact
Windows only. If a user has CRLF-ending files and runs
checkout/switch --mergethat produces conflicts, the conflict-marker stripping silently converts line endings, causing byte-offset drift between the cleaned content and the stashed VA. The result is degraded/misaligned attribution rather than a crash.Notes
GIT_CONFIG_NOSYSTEM=1suppressescore.autocrlf, and Windows CI tests were already failing for unrelated reasons before this PR.\r\n, or to normalize the stashed VA content to LF before computing offsets so both sides agree.Discovered via Devin PR review on #959.