CODE-016: centralize all sha1↔hex through dog/git/SHA1.h

A 2026-06-11 survey found sha1↔hex conversion done THREE overlapping ways across the tree: (1) the canonical dog/git/SHA1.h helpers (SHA1u8sFeedHex/a_sha1hex/HEXsha1Put encode, sha1FromBin/sha1Drain binary decode) used in ~17 files; (2) the dog/WHIFF.h sha1hex-struct path (sha1hexFromSha1/sha1FromSha1hex/sha1hexFromHex) at ~60 sites; (3) raw hand-rolled {sha->data, sha->data+20} + HEXu8sDrainSome/HEXu8sFeedSome at ~15 sites. SHA1.h is the canonical home for the sha1 type but lacks a hex→sha1 decode. Add the missing decode fn(s) to SHA1.h and route idioms (2) and (3) through it. Owned by the keeper worker; runs AFTER the current CODE batch lands to avoid reconcile churn (it touches keeper/graf/sniff/beagle/spot/dog). See CLAUDE, Issues.

Issues

Three overlapping sha1↔hex idioms; the canonical SHA1.h one has no hex decoder.

Blockers

Collides with the in-flight per-dir CODE worktrees (keeper/graf/sniff/beagle/spot/dog) — sequence after they land. Open design call: the sha1hex STRUCT (u8 data[40]) — keep as a value/key type where it earns it (sha1hexeq/sha1hexZ sorting/compare), or retire fully? Its CONVERSIONS unify regardless.

Planned

Add the decode fn to SHA1.h, then route every sha1↔hex site through SHA1.h.