Skip to content

fix(repo): add .gitattributes and stop CRLF from masquerading as metric drift #2

Description

@rxavier1979

Refs #1. Blocks #5, #7. Do this first.

Status: diagnosed 2026-08-20, not started.

Verified: all 42 released files contain CRLF in the working tree; git config core.autocrlf is true; the repo ships no .gitattributes.

Also verified: all 42 README byte metrics match exactly once line endings are normalized to LF (42/42), as do all 42 line counts and all 42 rule counts.

Not verified: behavior on a macOS checkout, and whether adding .gitattributes produces a whitespace-only diff against the upstream remote — run git add --renormalize . && git diff --stat and inspect before committing.

The central fact

The README is correct. There is no content drift.

A naive byte comparison reports 42/42 mismatches. Every one of them is the CR bytes. actual - claim equals the file's line count in all 42 cases:

clean-code/clean-code.md    claim=13851   raw=14148   delta=297   lines=297
refactoring/refactoring.md  claim=17866   raw=18299   delta=433   lines=433

This is a trap, not a defect in the data. Any lint that computes byte metrics without normalizing will emit 42 false failures on every Windows checkout, and an agent trusting that output will "fix" a README that was never wrong.

This is the third instance of this defect class in the operator's estate — see the open launchpad cards hub-gitattributes-crlf and gitattributes-crlf-blob-mismatch. Consider batching the diagnosis.

Goal

Make line endings deterministic in the repo, and make every downstream tool normalize before measuring.

Decisions (settled 2026-08-20)

# Decision Rationale
1 Add .gitattributes with *.md text eol=lf The corpus is text consumed by agents and by wc; LF is the canonical form the published metrics were computed in.
2 Do not rewrite history The blobs are already LF in git; only the working tree is CRLF. This is a checkout-filter problem, not a content problem.
3 Every metric tool normalizes \r\n to \n before counting bytes Belt and braces: .gitattributes fixes new clones, normalization fixes existing ones. A tool that is correct only on a correctly-configured clone is not correct.
4 Lint asserts absence of CR in released files Turns the invariant into a control that can fail.

Acceptance

  • .gitattributes present with *.md text eol=lf
  • git add --renormalize . produces no content change to any book file — verify with git diff --stat and attach the output
  • a fresh clone on Windows yields LF working-tree files
  • rules_lint.py byte check passes on both a CRLF and an LF working tree
  • decision-log 0002 — Line endings are LF, and every metric tool normalizes before counting

Verification

Re-run the diagnostic sweep. Expect 42/42 passing on all three metric families with normalization applied, and the CR check (lint check 8) flipping from FAIL to PASS.

Metadata

Metadata

Assignees

Labels

blockerBlocks other issues; do firsthygieneRepo hygiene, provenance, governancewave:1Wave 1 — foundations

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions