Skip to content

Pin LF line endings with a root .gitattributes - #13

Merged
DojoGenesis merged 1 commit into
mainfrom
fix/pin-lf-line-endings
Oct 23, 2026
Merged

DojoGenesis merged 1 commit into
mainfrom
fix/pin-lf-line-endings

Conversation

@DojoGenesis

Copy link
Copy Markdown
Owner

What

A root .gitattributes that pins LF line endings: * text=auto eol=lf, with *.md, *.py, *.sh, *.json, *.jsonl, *.js, *.ts, *.tsx, *.txt, *.yaml and *.yml named as text, and common binary types marked binary. Plus one CHANGELOG line under 2.4.0 / Fixed.

Why

On a Windows machine whose system git config sets core.autocrlf=true, a checkout of this repo gets CRLF files: plugins/dojo-protocol/PROTOCOL.md is 2014 bytes on disk against 1987 in git. The website's scripts/gen_proof.py --check counts bytes on disk, so every /proof figure read high, and since DojoGenesis/website#7 the deploy guard refuses a deploy unless the auditor passes. Until now a Windows deploy needed DOJO_PLUGINS_DIR pointed at an LF export (git -c core.autocrlf=false archive HEAD | tar -x). With this file, a plain clone is byte-exact.

Before choosing, I checked:

  • README.md, PORTABILITY.md and scripts/README-release.md state no line-ending policy.
  • git ls-files --eol on origin/main: all 1146 non-empty files are i/lf and none is binary (-text). The 1147th, scripts/tests_suite/__init__.py, is empty. No .bat, .cmd or .ps1 files, so nothing needs to stay CRLF.
  • The dojo-settle prereg sidecar (PREREG-2026-10-17-evidence.md.sha256) already hashes "CRLF as LF", so it is unaffected either way.

Verification

Run on Windows 11 with core.autocrlf=true (system config), in a fresh git worktree add --detach <worktree> fix/pin-lf-line-endings.

1. PROTOCOL.md checks out LF

$ git config --get core.autocrlf
true
$ git ls-files --eol plugins/dojo-protocol/PROTOCOL.md
i/lf    w/lf    attr/text eol=lf      	plugins/dojo-protocol/PROTOCOL.md
$ wc -c plugins/dojo-protocol/PROTOCOL.md ; git cat-file -s HEAD:plugins/dojo-protocol/PROTOCOL.md
1987 plugins/dojo-protocol/PROTOCOL.md
1987
$ git ls-files --eol | awk '{print $2}' | sort | uniq -c
   1147 w/lf
      1 w/none

The same w/ count on the CRLF checkout of main was 1131 w/crlf.

2. gen_proof --check matches disk

$ python3 dojogenesis-website/scripts/gen_proof.py --plugins-dir <worktree>/plugins --check
gen_proof: proof blocks match disk (date 2026-10-18)
rc=0

Control, the same command against the existing CRLF checkout of main:

gen_proof: public\proof.html differs from disk
gen_proof: public\es\proof.html differs from disk
rc=1

3. Renormalize stages nothing

$ git ls-files -z | xargs -0 git add --renormalize --
$ git diff --cached --numstat | wc -l
0

This passes every tracked path explicitly, the same set git add --renormalize . covers (renormalize only touches tracked files), because dojo-gates' staging guard blocks a bare git add ... .. It was also run in the authoring worktree before the commit: the only staged change was the 4-line CHANGELOG edit.

4. Release check: no regression; on this machine it can't reach PASS on main either

scripts/release-check.sh was run on this branch and on a fresh worktree of origin/main (c676050), with the same environment for each. This Windows machine has no Python 3.9 and no local denylist lists, so neither tree can reach OVERALL: PASS here.

  • Defaults: both trees give the same table, OVERALL: FAIL (0 fail, 20 error, 1 warn-ok, 0 warn). All 20 errors are python 3.9 interpreter not found. The rows that ran pass on both: mod:dojo-router (27 tests), mod:dojo-meter (54), mod:dojo-verify (109), face-parity (CONTRACT PASS) and always-on; plugin-lint is WARN-OK (known quarantine baseline).
  • DOJO_PY39 set to Python 3.10.7, to exercise the Python rows: both trees give OVERALL: FAIL (8 fail, 1 error, 1 warn-ok, 1 warn). lint and all nine validate:* rows pass. The unittest FAIL rows and self-test FAIL are Windows test-portability failures, identical on main. denylist is ERROR because the lists are missing. One row differs:
main:   unittest:dojo-protocol  FAIL  exit 1: FAILED (failures=75, errors=1, skipped=3)
branch: unittest:dojo-protocol  FAIL  exit 1: FAILED (failures=74, errors=1, skipped=3)

The one fewer failure is test_session_start.TestInjection.test_protocol_md_canonical, which fails on the CRLF checkout and passes on the LF one.

A release-check run on the Mac (Python 3.9 at /usr/bin/python3, denylist lists present) is the one that can show OVERALL: PASS.

After merging

The shared Windows checkout keeps its CRLF files on disk after the merge. A plain git -C C:\Users\cruzr\CoworkPluginsByDojoGenesis checkout -- . is not enough: git skips every file whose stat info still matches the index. Tested on a CRLF worktree of this branch, it left all 1146 files w/crlf. Touching the tracked files first makes git rewrite them. Once git status --short prints nothing (this overwrites local edits), run in Git Bash:

cd C:/Users/cruzr/CoworkPluginsByDojoGenesis
git ls-files -z | xargs -0 touch --
git checkout -- .
git ls-files --eol | awk '{print $2}' | sort | uniq -c

On the test worktree, the last line printed 1147 w/lf and 1 w/none, with PROTOCOL.md at 1987 bytes and a clean status. After that, DOJO_PLUGINS_DIR can point at the checkout directly, with no LF export needed.

🤖 Generated with Claude Code

A Windows clone with core.autocrlf=true checked every text file out with
CRLF, so plugins/dojo-protocol/PROTOCOL.md was 2014 bytes on disk against
1987 in git. The website's gen_proof.py --check counts bytes on disk, so
every /proof figure read high and the deploy guard refused the deploy
unless DOJO_PLUGINS_DIR pointed at an LF export.

* text=auto eol=lf, with the common text types named and binaries marked.
The index was already all LF: renormalizing stages no content changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@DojoGenesis
DojoGenesis merged commit c75b259 into main Oct 23, 2026
3 checks passed
@DojoGenesis
DojoGenesis deleted the fix/pin-lf-line-endings branch October 23, 2026 23:33
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.

2 participants