Skip to content

fix(standard): §6.5 gate reads the index, not the working tree — v2.02 - #34

Merged
UnbreakableMJ merged 2 commits into
mainfrom
fix/6.5-gate-checks-stored-content
Sep 13, 2026
Merged

UnbreakableMJ merged 2 commits into
mainfrom
fix/6.5-gate-checks-stored-content

Conversation

@UnbreakableMJ

Copy link
Copy Markdown
Contributor

§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:

git grep -Il $'\r' -- .

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=crlf is stored LF in the repository and checked out CRLF by design — that is the entire point of the pin. git grep reads 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. achernar carries a gradlew.bat — which cmd.exe requires in CRLF — and that is the case that found it.

Reproduced directly:

$ git ls-files --eol
i/lf    w/lf    attr/text=auto eol=lf   ok.rs
i/lf    w/crlf  attr/text eol=crlf      win.bat     <- correctly pinned
$ git grep -Il $'\r' -- .
win.bat                                             <- gate fails anyway

The fix

The gate now reads what is stored:

bad=$(git ls-files --eol | awk -F'\t' '$1 ~ /i\/(crlf|mixed)/ {print $2}')
Index state Meaning Verdict
i/lf stored LF — includes correctly pinned eol=crlf files pass
i/crlf, i/mixed CRLF in the repository fail
i/-text binary, not a text file n/a

Validated against real repositories: ironway reports exactly 129 (matching the independent count), bravais 2, achernar 2, standard/engram 0.

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

.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. 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

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread .github/workflows/ci.yml Outdated
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}')

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

Comment thread .github/workflows/ci.yml Outdated
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}')

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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
@UnbreakableMJ
UnbreakableMJ merged commit d379fc8 into main Sep 13, 2026
2 checks passed
@UnbreakableMJ
UnbreakableMJ deleted the fix/6.5-gate-checks-stored-content branch September 13, 2026 03:39
@UnbreakableMJ
UnbreakableMJ restored the fix/6.5-gate-checks-stored-content branch September 14, 2026 15:05
@UnbreakableMJ
UnbreakableMJ deleted the fix/6.5-gate-checks-stored-content branch September 14, 2026 15:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant