BLAME-001: blame walks all ancestors, re-inflating unchanged blobs

graf blame:<path> costs O(total history), not O(file history). GRAFFileWeave (graf/BLAME.c) topo-walks the tip's full ancestor closure (nord) and calls GRAFBlobAtCommit (graf/BLOB.c) for every commit — inflating the commit object, each path tree, and the (large) file blob from keeper — then byte-dedups AFTER the fetch. Measured (release): blame:graf/GRAF.c 0.34s (1.16s debug+ASAN), nord=1545 for EVERY file regardless of its 11–116-commit history, ~16 inflates/commit, only ~12% of fetches yield a fold. The fix is keeper-side, no index format change: compare object hashes top-down (each child OID is free in its parent tree), stop at the highest unchanged subtree, and inflate the blob + fold only when the leaf OID actually changed. The deeper index-side variant is BLAME-002; parallelism is BLAME-003. See Plan.

Issues

Cost scales with total repo history, not the file's; the big blob is re-inflated at every ancestor, then discarded.

Blockers

None. Keeper-side only, no on-disk .graf.idx format change; each step lands green and ships independently.

Planned

Compare object hashes top-down, stop at the highest unchanged subtree, and inflate a blob only when its OID actually changed.

Landed

None yet.