Problem
20 files are committed on main with CRLF line endings, and the repo has no .gitattributes to stop
more from landing. The changes CI job runs:
git diff --check "$BASE_SHA" HEAD
Git's default core.whitespace is blank-at-eol,space-before-tab,blank-at-eof with cr-at-eol
off, so a carriage return at end-of-line is trailing whitespace as far as --check is concerned.
Any PR that adds a line to one of these files therefore fails CI with an error pointing at lines whose
visible content is spotless, and nothing in the output ever says "CRLF".
This is not hypothetical — it already produced a red changes job on #9787
(run 30436384202):
src/review/inline-suggestion-anchor.ts:13: trailing whitespace.
+ for (const raw of patch.split("\n")) {
src/review/inline-suggestion-anchor.ts:21: trailing whitespace.
+ if (marker === undefined || marker === "-" || marker === "\\") continue;
##[error]Process completed with exit code 2.
Neither line has trailing whitespace. The author did nothing wrong; their editor preserved the file's
existing CRLF convention on the lines they added. There is no way to work that out from the log — it
takes cloning the branch and hexdumping the file.
The whitespace step only started catching this recently: it used to run git diff --check with no
arguments against a shallow single-commit checkout, where working tree and index are always identical,
so it unconditionally passed. Fixing that false-green turned these pre-existing CRLF files into a live
CI trap.
Affected files
Eleven under src/, test/ and packages/:
packages/loopover-engine/src/signals/issue-quality-report.ts
src/review/changed-files-diff-link.ts
src/review/inline-comment-label.ts
src/review/inline-comment-range.ts
src/review/inline-suggestion-anchor.ts
test/unit/changed-files-diff-link.test.ts
test/unit/inline-comment-label.test.ts
test/unit/inline-comment-range.test.ts
test/unit/inline-comments-select.test.ts
test/unit/inline-suggestion-anchor.test.ts
test/unit/issue-quality-report-package.test.ts
…plus nine more under review-enrichment/ with the same defect:
review-enrichment/src/analyzers/binary-extensions.ts
review-enrichment/test/binary-extensions.test.ts
review-enrichment/test/codeowners.test.ts
review-enrichment/test/debug-leftover.test.ts
review-enrichment/test/dependency-diff.test.ts
review-enrichment/test/floating-promise.test.ts
review-enrichment/test/hardcoded-url.test.ts
review-enrichment/test/i18n-regression.test.ts
review-enrichment/test/size-smell.test.ts
Four are mixed — src/review/inline-comment-range.ts is 36 CRLF lines out of 54, test/unit/inline-comment-range.test.ts 66 of 97 — so which lines trip the check depends on where in the file you edit.
Reproduce:
git grep -lI $'\r' origin/main -- .
Expected
- All 20 files converted to LF, content otherwise byte-identical (
git diff -w shows no substantive
change) and their unit tests still passing.
- A root
.gitattributes pinning the repo to LF so this cannot recur. It must be * text=auto eol=lf,
not * text eol=lf — five .ts files embed NUL bytes on purpose as untrusted-text/sanitizer
fixtures (test/unit/mcp-untrusted-text.test.ts, src/services/maintainer-recap-routing.ts,
review-enrichment/src/analyzers/ci-check-signals.ts, scripts/counterfactual-replay-core.ts,
packages/loopover-engine/test/governor-ledger.test.ts). text=auto leaves git's binary detection
in charge and passes them through untouched; forcing text would rewrite them.
- The
changes job should say CRLF when it means CRLF. .gitattributes stops CRLF entering
through git add, but checkin filters don't run on blobs written directly (GitHub web editor, the
Contents API) or on a merge of a branch cut before .gitattributes landed, so the diagnostic is
still worth having — and "trailing whitespace" on a clean-looking line is the single hardest CI
failure in this repo to diagnose.
Problem
20 files are committed on
mainwith CRLF line endings, and the repo has no.gitattributesto stopmore from landing. The
changesCI job runs:git diff --check "$BASE_SHA" HEADGit's default
core.whitespaceisblank-at-eol,space-before-tab,blank-at-eofwithcr-at-eoloff, so a carriage return at end-of-line is trailing whitespace as far as
--checkis concerned.Any PR that adds a line to one of these files therefore fails CI with an error pointing at lines whose
visible content is spotless, and nothing in the output ever says "CRLF".
This is not hypothetical — it already produced a red
changesjob on #9787(run 30436384202):
Neither line has trailing whitespace. The author did nothing wrong; their editor preserved the file's
existing CRLF convention on the lines they added. There is no way to work that out from the log — it
takes cloning the branch and hexdumping the file.
The whitespace step only started catching this recently: it used to run
git diff --checkwith noarguments against a shallow single-commit checkout, where working tree and index are always identical,
so it unconditionally passed. Fixing that false-green turned these pre-existing CRLF files into a live
CI trap.
Affected files
Eleven under
src/,test/andpackages/:packages/loopover-engine/src/signals/issue-quality-report.tssrc/review/changed-files-diff-link.tssrc/review/inline-comment-label.tssrc/review/inline-comment-range.tssrc/review/inline-suggestion-anchor.tstest/unit/changed-files-diff-link.test.tstest/unit/inline-comment-label.test.tstest/unit/inline-comment-range.test.tstest/unit/inline-comments-select.test.tstest/unit/inline-suggestion-anchor.test.tstest/unit/issue-quality-report-package.test.ts…plus nine more under
review-enrichment/with the same defect:review-enrichment/src/analyzers/binary-extensions.tsreview-enrichment/test/binary-extensions.test.tsreview-enrichment/test/codeowners.test.tsreview-enrichment/test/debug-leftover.test.tsreview-enrichment/test/dependency-diff.test.tsreview-enrichment/test/floating-promise.test.tsreview-enrichment/test/hardcoded-url.test.tsreview-enrichment/test/i18n-regression.test.tsreview-enrichment/test/size-smell.test.tsFour are mixed —
src/review/inline-comment-range.tsis 36 CRLF lines out of 54,test/unit/inline-comment-range.test.ts66 of 97 — so which lines trip the check depends on where in the file you edit.Reproduce:
Expected
git diff -wshows no substantivechange) and their unit tests still passing.
.gitattributespinning the repo to LF so this cannot recur. It must be* text=auto eol=lf,not
* text eol=lf— five.tsfiles embed NUL bytes on purpose as untrusted-text/sanitizerfixtures (
test/unit/mcp-untrusted-text.test.ts,src/services/maintainer-recap-routing.ts,review-enrichment/src/analyzers/ci-check-signals.ts,scripts/counterfactual-replay-core.ts,packages/loopover-engine/test/governor-ledger.test.ts).text=autoleaves git's binary detectionin charge and passes them through untouched; forcing
textwould rewrite them.changesjob should say CRLF when it means CRLF..gitattributesstops CRLF enteringthrough
git add, but checkin filters don't run on blobs written directly (GitHub web editor, theContents API) or on a merge of a branch cut before
.gitattributeslanded, so the diagnostic isstill worth having — and "trailing whitespace" on a clean-looking line is the single hardest CI
failure in this repo to diagnose.