fix(standard): sync §6.5 gate correction — v2.02 - #59
Conversation
Skill-side sync of Standard PR #34. The v1.51 gate grepped the working tree and claimed a pinned eol=crlf exception was invisible to git grep. It is not: such a file is stored LF and checked out CRLF by design, so the grep finds the CR the pin deliberately put there and fails the build — punishing the exception §6.5 grants. achernar gradlew.bat is the case that found it. The gate now reads the index: git ls-files --eol reports i/lf, i/crlf or i/mixed, and any i/crlf or i/mixed is CRLF in the repository. Also recorded: .gitattributes does not retroactively normalize blobs already committed with CRLF, so adoption in an affected repo is two acts — config files plus a renormalization commit. Both bundles rebuilt. Description 993 chars, under the §5.6 cap. 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: 08c5351de4
ℹ️ 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".
| | `.gitattributes` required | Every repository MUST ship `.gitattributes` at its root containing `* text=auto eol=lf`. This is the only mechanism that holds regardless of a contributor's `core.autocrlf` setting — which defaults to `true` on Windows and rewrites the working tree on checkout. Relying on per-clone Git configuration is not compliance. | | ||
| | `.editorconfig` required | Every repository MUST ship `.editorconfig` at its root with `root = true` and, under `[*]`, at minimum `charset = utf-8`, `end_of_line = lf`, and `insert_final_newline = true`. It carries the rule to editors that never consult Git. | | ||
| | CI gate | CI MUST fail when a tracked text file contains a CR byte. Both config files are advisory to the tools that read them; the gate is what makes the rule binding. `git grep -Il` needs no exclusion list — it skips binaries and honors `.gitattributes`, so a pinned exception is invisible to it. | | ||
| | CI gate | CI MUST fail when a tracked text file is **stored** with CRLF. Both config files are advisory to the tools that read them; the gate is what makes the rule binding. The gate reads the index, not the working tree — `git ls-files --eol` reports the stored line ending as `i/lf`, `i/crlf` or `i/mixed`, and any `i/crlf` or `i/mixed` is a violation (`i/-text` is binary, not a text file). Grepping the working tree for a CR byte is **not** a correct implementation: a file pinned `eol=crlf` is stored LF and checked out CRLF by design, so a working-tree grep fails the very exception this section grants. | |
There was a problem hiding this comment.
Migrate Construct's gate to the index
This declares working-tree grep incorrect, but .github/workflows/text-file-format.yml lines 28–33 still runs git grep -Il "$CR" -- .. Once Construct adds a permitted eol=crlf path, checkout deliberately gives that file CRLF and the unchanged job rejects every PR containing it. Update that workflow and its comments with this change; git grep -h explicitly describes --cached as “search in index instead of in the work tree,” which preserves the existing binary filtering while inspecting stored blobs.
AGENTS.md reference: AGENTS.md:L47-L52
Useful? React with 👍 / 👎.
| | `.gitattributes` required | Every repository MUST ship `.gitattributes` at its root containing `* text=auto eol=lf`. This is the only mechanism that holds regardless of a contributor's `core.autocrlf` setting — which defaults to `true` on Windows and rewrites the working tree on checkout. Relying on per-clone Git configuration is not compliance. | | ||
| | `.editorconfig` required | Every repository MUST ship `.editorconfig` at its root with `root = true` and, under `[*]`, at minimum `charset = utf-8`, `end_of_line = lf`, and `insert_final_newline = true`. It carries the rule to editors that never consult Git. | | ||
| | CI gate | CI MUST fail when a tracked text file contains a CR byte. Both config files are advisory to the tools that read them; the gate is what makes the rule binding. `git grep -Il` needs no exclusion list — it skips binaries and honors `.gitattributes`, so a pinned exception is invisible to it. | | ||
| | CI gate | CI MUST fail when a tracked text file is **stored** with CRLF. Both config files are advisory to the tools that read them; the gate is what makes the rule binding. The gate reads the index, not the working tree — `git ls-files --eol` reports the stored line ending as `i/lf`, `i/crlf` or `i/mixed`, and any `i/crlf` or `i/mixed` is a violation (`i/-text` is binary, not a text file). Grepping the working tree for a CR byte is **not** a correct implementation: a file pinned `eol=crlf` is stored LF and checked out CRLF by design, so a working-tree grep fails the very exception this section grants. | |
There was a problem hiding this comment.
Keep rejecting stored lone CR bytes
Checking only i/crlf and i/mixed does not enforce line 624's explicit lone-CR prohibition. With the required * text=auto eol=lf, a staged text fixture containing a\rb\n is reported by Git 2.43 as i/-text, so this prescribed gate treats it as binary and passes it; i/-text is a classification, not proof that the content is actually binary. An index-content check such as git grep --cached -Il "$CR" catches this case while a pinned eol=crlf file still passes because its stored blob is LF (git grep -h confirms that --cached searches the index).
AGENTS.md reference: AGENTS.md:L47-L52
Useful? React with 👍 / 👎.
A path pinned `-text` is declared binary; git does no eol conversion, so its blob keeps CRLF and ls-files reports i/crlf though it is not a text file. 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
Skill-side sync of Standard#34. Same version and date — v2.02 (2026-09-12).
§6.5's v1.51 gate grepped the working tree and claimed a pinned
eol=crlfexception was invisible togit grep. It is not — such a file is stored LF and checked out CRLF by design, so the grep finds the CR the pin deliberately put there and fails the build, punishing the very exception §6.5 grants.achernar'sgradlew.batis the case that found it.The gate now reads the index:
git ls-files --eolreportsi/lf,i/crlfori/mixed; anyi/crlfori/mixedis CRLF in the repository. A pinned file reportsi/lfand passes; a binary reportsi/-text.Also recorded:
.gitattributesdoes not retroactively normalize blobs already committed with CRLF (bravaisproves it), so adoption in an affected repo is two acts — config files plus a renormalization commit.Description measures 993 characters, under the §5.6 cap. Both bundles rebuilt.
🤖 Generated with Claude Code
https://claude.ai/code/session_01XGgUmYtDJxo8EMKyB5LdoV