---
name: compare-at-one-layer-crlf-meter-class
description: "CRLF meter class (3 instances, one day, 3 different agents): any byte comparison taking one side from the working tree and the other from git's normalized view lies toward DAMAGE. Rule: compare at ONE layer — both raw, both normalized, or both content-addressed."
metadata: 
  node_type: memory
  type: project
  originSessionId: ffecabec-8000-44d0-ae77-bf3aaf8c4615
  modified: 2026-08-29T05:16:20.243Z
---

**The rule (deployah's formulation, 2026-08-29, CONDUIT respin arc):** COMPARE AT ONE LAYER.
Both sides normalized, both sides raw, or both sides through git's content-addressed view
(`git hash-object` disk file vs `git rev-parse HEAD:path`). Never one of each. "Use hash-object"
is one instance, not the rule.

**Mechanism:** this repo checks out CRLF while committed blobs are LF, so the working tree and the
object store are two DIFFERENT byte sequences for identical content. A mixed-layer comparison is
the NATURAL one to write (the file in hand is on disk; the trusted copy is in git) and it fails
toward MISMATCH — the expensive direction, because a false "damaged restore" mid-mutation-cycle
makes you distrust a good tree or re-run cycles; and a meter that cries damage gets disabled as
fast as one that never fires, leaving the real failure unprotected.

**The three instances, one day:**
1. doyle: mutation-cycle byte-identity checker — subprocess `text=True` normalized `git show`
   output vs raw disk bytes ⇒ printed restore_byte_identical=NO ×4; hash-object refuted it.
2. todlando: sha256(restored working copy) vs pre-mutation baseline ⇒ MISMATCH off by exactly its
   840 line terminators (42,536 bytes / 840 CRLF on disk against a 41,696-byte / 840-LF blob);
   normalized == committed blob == baseline, `git status` clean. releases#240 fixup cycle.
3. deployah ×2, unrecognized as measurement: `xtask gen` reported reference.md MODIFIED on both
   shapings; `git diff --ignore-cr-at-eol` showed zero content change — phantom diff reverted as
   "churn" without naming the mechanism.

**Sound inference kept:** a restore assertion that PASSED on Windows under a mixed-layer meter was
passing on genuinely unfiltered bytes — passes stay valid, only the false alarms are retracted.

**The assertion stays MANDATORY — only its OPERAND was wrong.** Keep committing the baseline before
mutating ([[restore-step-presumes-committed-baseline]]: `git checkout --` restores from HEAD, so
running it over uncommitted work destroys the thing being proved). This entry fixes what the check
compares, never whether to check.

Distinct from [[lane-diff-byte-identity-limit]] — there the diff HEADERS move across a rebase while
content holds; here content is untouched and only its terminators are rewritten. Both defeat a raw
byte-compare, for different reasons.

Kin: [[identical-readings-across-opposite-outcomes-indict-the-meter]],
[[include-str-fixture-inherits-checkout-eol]] (the product-side face of the same checkout filter),
[[mutation-proof-does-not-validate-a-green]] (same arc).
