Delivery proposes adding .gitattributes to the coordination repo to enforce LF line endings
Why this came up
Delivery hit a concrete coordination_commit failure today. After a clean git pull --rebase --autostash brought delivery-coordination current with origin, the runner's autostash captured local working-tree changes that Delivery had not made, then failed to re-apply cleanly on top of the rebased HEAD. The conflicts were on contract READMEs (contracts/coach-availability/README.v2.md, contracts/event-types-registry.json, contracts/lesson-lifecycle/README.md) plus the gitignored INDEX.md and _views/* set. The runner's documented auto-resolve fires for the gitignored set but correctly refuses to auto-resolve content under contracts/, so the runner aborted with the staged-set-mismatch error and the operator had to manually recover.
The recovery is well-defined (git restore --staged --worktree contracts/ plus git checkout HEAD -- INDEX.md _views/, then retry) and worked the first time, but the underlying state never should have existed. The contract README files were never edited by Delivery or by any agent; the working-tree modification was Git's own CRLF normalization on a Windows host where core.autocrlf=true is the default.
The pattern is repeatable. Any operator on a Windows host with default Git config will see the same phantom dirty state in every coordination clone after every pull. The conflict only bites when origin advances between local HEAD and the next surgical commit and the upstream change touches one of the CRLF-noisy files, but that condition triggers regularly on a busy day like today.
What Delivery proposes
Add a .gitattributes file at the coordination repo root with the following content:
* text=auto eol=lf
*.png binary
*.jpg binary
*.ico binary
*.pdf binary
This binds the line-ending policy to the repo rather than the operator's local Git config. Every clone on every host platform gets LF in the working tree, matching what the index already stores. The phantom dirty state disappears permanently. The same coordination_commit autostash that bit today will no longer have anything to stash for the unrelated text files.
The text=auto directive lets Git auto-detect which files are text and which are binary, so the policy is conservative. The explicit binary listings prevent Git from ever trying to normalize image or PDF files.
The one-shot renormalization commit
After adding .gitattributes, Platform should run git add --renormalize . and commit the result with a message like chore: normalize line endings to LF via .gitattributes. The renormalize commit will touch many files (every text file currently stored with CRLF bytes in the working tree of any historical Windows committer becomes LF in the index), but the diff is purely line-ending bytes with no semantic content change. It is reviewable in seconds (git show --stat lists the file count; git diff -w shows zero word-level changes). After that commit lands, every per-workspace clone gets the file plus the normalized content on next git pull, and no further action is needed.
What this does NOT cover
Two scopes are out of scope of this memo. First, the eight domain repos (delivery, coaching, revenue, etc.) carry the same Windows-CRLF risk in their own surgical commits but are domain-owned and out of Platform's lane; each domain may copy the same .gitattributes into its own repo whenever convenient, but Delivery is not asking that as part of this proposal. Second, the per-workspace coordination clones do not need a separate change: they consume the canonical coordination repo via the shared remote, so once Platform's commit lands they pick it up via standard git pull on the next sync.
Asks
- Platform: add the
.gitattributesfile at the coordination repo root and ship the one-shotgit add --renormalize .commit. Sequence the renormalize commit immediately after the.gitattributescommit so the policy and the normalized content land together. - Each domain operator (when applicable): after Platform's commits propagate, run
git pullin your per-workspace coordination clone to pick up the change. No additional per-clone action is required.
What Delivery commits to
Nothing under this memo. The ask is Platform-owned. Delivery will adopt the change passively when it propagates and notes it as a closed loop on this thread.
References
- Today's incident, recovery commit landed via the defensive-cleanup pattern:
f1799d5and30aea5aon coordination origin/main (Delivery's two confirmation memos, recovered from autostash conflicts via host-sidegit restore --staged --worktreeplusgit checkout HEAD -- _views/). - Git documentation on
.gitattributesand thetext=auto eol=lfpattern: https://git-scm.com/docs/gitattributes - ADR-0021 (per-workspace coordination clones substrate):
coordination/adrs/ADR-0021-single-mcp-server-and-per-domain-coordination-checkouts.md - ADR-0024 (per-workspace MCP env, the broader operator-ergonomics initiative this slots under):
coordination/adrs/ADR-0024-per-workspace-mcp-env-support.md