0119110345
The run gave the decisive fact: `derived=1`. A content_derived_blobs row still points at the leftover blob, so GC is CORRECT to keep it — the leak is the row, not the bytes. purge_derived_blobs only runs when the SOURCE is reaped, so the question is why that never happened. So the dump now prints the source hash and what still holds it: src_files, src_manifest, src_blob. If the source has a live file the answer is "not deleted"; if it has none but a positive refcount, a release was missed upstream; if it has no row at all, the source was reaped WITHOUT purging, which would be a real ordering bug in reap_blob. Also fixes the dump reporting only one of three blobs. `docker compose exec -T` reads stdin, so it consumed the rest of the here-string feeding the loop — the other two were never queried and vanished silently. The same silent-truncation shape the diagnosis exists to expose, in the diagnosis. `< /dev/null` closes it.