Documents what nwsync emit --out DIR actually produces, so a zone can be checked by hand.
The trap this removes: a blob's filename is the SHA-1 of the resource's original bytes, but the file on disk is NWCompressedBuffer framing — a 24-byte NSYC header then a zstd frame. sha1sum <blob> therefore never matches the name it is sitting under. The doc records the recipe that does match:
tail -c +25 <blob> | zstd -dc | sha1sum
Also notes the tree layout, that the uncompressed length is a little-endian uint32 at offset 12, and the rough 4:1 compression ratio on hak content.
Verified two ways: against a real emit of a 250 MB hak (2296 blobs, 59 MB on disk against 249 MB of resources), and against internal/nwsync/compressedbuf.go, where the header is written as []uint32{blobMagic, blobVersion, algorithmZstd, uint32(len(data)), zstdHeaderVer, zstdDictionary} — confirming field 3 at offset 12.
Docs only, no behaviour change. Falls out of the investigation in #76; that fix is not in this PR.
Documents what `nwsync emit --out DIR` actually produces, so a zone can be checked by hand.
The trap this removes: a blob's filename is the SHA-1 of the resource's *original* bytes, but the file on disk is NWCompressedBuffer framing — a 24-byte `NSYC` header then a zstd frame. `sha1sum <blob>` therefore never matches the name it is sitting under. The doc records the recipe that does match:
```
tail -c +25 <blob> | zstd -dc | sha1sum
```
Also notes the tree layout, that the uncompressed length is a little-endian `uint32` at offset 12, and the rough 4:1 compression ratio on hak content.
Verified two ways: against a real emit of a 250 MB hak (2296 blobs, 59 MB on disk against 249 MB of resources), and against `internal/nwsync/compressedbuf.go`, where the header is written as `[]uint32{blobMagic, blobVersion, algorithmZstd, uint32(len(data)), zstdHeaderVer, zstdDictionary}` — confirming field 3 at offset 12.
Docs only, no behaviour change. Falls out of the investigation in #76; that fix is not in this PR.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Blob filenames are the SHA-1 of a resource's original bytes, but the file on
disk is NWCompressedBuffer framing: a 24-byte NSYC header then a zstd frame.
Hashing the file directly is the first thing anyone tries when checking a zone
by hand, and it never matches. Record the layout and the one-line recipe that
does match, plus where the uncompressed length lives in the header.
Verified against a real emit and against internal/nwsync/compressedbuf.go.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
xtul
approved these changes 2026-07-31 10:55:07 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Documents what
nwsync emit --out DIRactually produces, so a zone can be checked by hand.The trap this removes: a blob's filename is the SHA-1 of the resource's original bytes, but the file on disk is NWCompressedBuffer framing — a 24-byte
NSYCheader then a zstd frame.sha1sum <blob>therefore never matches the name it is sitting under. The doc records the recipe that does match:Also notes the tree layout, that the uncompressed length is a little-endian
uint32at offset 12, and the rough 4:1 compression ratio on hak content.Verified two ways: against a real emit of a 250 MB hak (2296 blobs, 59 MB on disk against 249 MB of resources), and against
internal/nwsync/compressedbuf.go, where the header is written as[]uint32{blobMagic, blobVersion, algorithmZstd, uint32(len(data)), zstdHeaderVer, zstdDictionary}— confirming field 3 at offset 12.Docs only, no behaviour change. Falls out of the investigation in #76; that fix is not in this PR.
🤖 Generated with Claude Code