fix(standard): §6.5 gate reads the index, not the working tree — v2.02 - #34
Conversation
v1.51 required CI to fail when "a tracked text file contains a CR byte" and left the implementation to the reader. The reference implementation grepped the working tree (`git grep -Il $'\r'`), with a note claiming git grep honors .gitattributes so a pinned exception is invisible to it. That claim is false, and it breaks the exception §6.5 itself grants. A file pinned `*.bat text eol=crlf` is stored LF and checked out CRLF by design — that is the point of the pin. git grep reads the working tree, finds the CR the pin deliberately put there, and fails the build. The rule granted an exception in one row and punished it in the next; the rows only appeared to agree because no repo had yet needed a pin. achernar's gradlew.bat is the case that found it. The gate now reads what is stored. `git ls-files --eol` reports the index line ending as i/lf, i/crlf or i/mixed; any i/crlf or i/mixed is CRLF in the repository, which is what §6.5 was always about. A pinned eol=crlf file reports i/lf and passes; a binary reports i/-text; a file committed with CRLF before .gitattributes existed reports i/crlf and fails, which is the case the section exists to catch. Also recorded: .gitattributes does not retroactively normalize blobs already committed with CRLF. bravais has carried `* text=auto eol=lf` for months and still reports two i/crlf files. Adoption in a repo that already carries CRLF is two acts — the config files, and a renormalization commit — not one. This repository's own CI step is corrected to match. No other §6.5 rule changes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XGgUmYtDJxo8EMKyB5LdoV
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c542fa74fc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| CR=$(printf '\r') | ||
| if git grep -Il "$CR" -- .; then | ||
| echo "::error::CR byte in a tracked text file — §6.5 requires LF line endings" | ||
| bad=$(git ls-files --eol | awk -F'\t' '$1 ~ /i\/(crlf|mixed)/ {print $2}') |
There was a problem hiding this comment.
Honor the declared stored-CRLF exceptions
When an exception must retain CRLF in the repository—such as a vendored upstream file or a format whose specification mandates CRLF—the index legitimately reports i/crlf, and this unconditional filter fails CI even if .gitattributes explicitly pins the exception; marking it -text does not help because --eol still derives the index EOL classification from the blob. The Git ls-files --eol documentation confirms that i/<eolinfo> describes index contents. Consult the attributes or an explicit exception set before rejecting these entries, otherwise the new gate contradicts the Exceptions row at The_Steelbore_Standard.texi:1338-1345.
Useful? React with 👍 / 👎.
| @documentencoding UTF-8 | ||
| @documentlanguage en | ||
| @settitle The Steelbore Standard 2.01 | ||
| @settitle The Steelbore Standard 2.02 |
There was a problem hiding this comment.
Sign this version-changing commit before merging
The raw commit object for f362cdd3362be874b46d8b840fe78bc993904f3a has no gpgsig header, and git verify-commit fails, so this release commit cannot appear Verified on GitHub. Recreate it with a cryptographic signature before merging; signed commits are explicitly non-negotiable for programmatic changes in this repository.
AGENTS.md reference: AGENTS.md:L90-L90
Useful? React with 👍 / 👎.
| CR=$(printf '\r') | ||
| if git grep -Il "$CR" -- .; then | ||
| echo "::error::CR byte in a tracked text file — §6.5 requires LF line endings" | ||
| bad=$(git ls-files --eol | awk -F'\t' '$1 ~ /i\/(crlf|mixed)/ {print $2}') |
There was a problem hiding this comment.
Reject lone-CR text in the index gate
For a tracked UTF-8 text file whose lines use only lone CR—explicitly prohibited at The_Steelbore_Standard.texi:1297-1300—Git 2.43 reports i/-text, not i/crlf or i/mixed, even when the path has an explicit text attribute, so this filter silently passes the violation. The Git ls-files --eol documentation describes -text as Git considering the contents binary, which is only a heuristic and does not establish that the file is outside this standard's text-file scope; inspect index blob bytes or otherwise account for lone CR without scanning the transformed working tree.
Useful? React with 👍 / 👎.
A path pinned `-text` is declared binary; git does no eol conversion on it, so its blob keeps CRLF and ls-files reports i/crlf even though the file is not a text file at all. The gate flagged it, which would fail a saved MIME archive or a binary git cannot auto-detect — found on a PDF with no NUL bytes in its first 8KB, which git classifies as text. The gate now skips attr/-text. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XGgUmYtDJxo8EMKyB5LdoV
§6.5's CI gate as shipped at v1.51 breaks the exception §6.5 itself grants. Found while preparing the CRLF-renormalization wave of the rollout.
The bug
v1.51 required CI to fail when "a tracked text file contains a CR byte" and left the implementation to the reader. The reference implementation grepped the working tree:
with a note claiming
git grep"honors.gitattributes, so a pinned exception is invisible to it and needs no exclusion list."That claim is false. A file pinned
*.bat text eol=crlfis stored LF in the repository and checked out CRLF by design — that is the entire point of the pin.git grepreads the working tree, finds the CR the pin deliberately put there, and fails the build.So §6.5 granted an exception in its Exceptions row and shipped a gate that punished it in its CI-gate row. The two only appeared to agree because no repository had yet needed a pinned exception.
achernarcarries agradlew.bat— whichcmd.exerequires in CRLF — and that is the case that found it.Reproduced directly:
The fix
The gate now reads what is stored:
bad=$(git ls-files --eol | awk -F'\t' '$1 ~ /i\/(crlf|mixed)/ {print $2}')i/lfeol=crlffilesi/crlf,i/mixedi/-textValidated against real repositories:
ironwayreports exactly 129 (matching the independent count),bravais2,achernar2,standard/engram0.The row now specifies the mechanism rather than leaving it to the implementer, and says plainly that a working-tree grep is not a correct implementation.
Second fact recorded
.gitattributesdoes not retroactively normalize blobs already committed with CRLF.bravaishas carried* text=auto eol=lffor months and still reports twoi/crlffiles. Adopting §6.5 in a repository that already carries CRLF is therefore two acts — the config files, and a renormalization commit — and a rollout shipping only the first leaves the damage in place while reporting success.Scope
Nothing else in §6.5 changes: the three format rules, both required config files, the exception set, and the scope note are exactly as v1.51 left them. This repository's own CI step is corrected to match.
The 22 rollout repositories carry the old gate and need the same correction; that follows as its own wave.
🤖 Generated with Claude Code
https://claude.ai/code/session_01XGgUmYtDJxo8EMKyB5LdoV