Stamps: what they promise, and what they cannot
Two different things could be asked of a build's stamp, and they are different on purpose (issue #5 §6, decision 8): canonical-content equality is mandatory; stamp identity is an aspiration. This file is why the aspiration cannot be an assertion — what a stamp can promise, what it cannot by construction, and what is enforced instead.
Why a stamp cannot be recomputed from a bundle
A build's stamp is an order-independent SHA-256 over named part hashes
(docs/ §8.1). Five kinds of part go into it:
| Part | Hash of | Recoverable from the bundle? |
|---|---|---|
worlds/ |
the encoded world payload | yes — read the entry, hash it |
worlds/ |
the packed locations | yes |
worlds/ |
the encoded text payload | yes |
icons/ |
the icon's bytes | yes |
atlas.json |
the encoded manifest, with version.stamp and version.createdAt blank |
yes — blank the two fields and re-encode |
tiles/ |
the pyramid's own derivation stamp | no |
The last row is the whole difficulty. A pyramid's part hash is not a hash of
the tiles in the archive; it is the stamp the tile pipeline computed when it
derived the pyramid, which already names the source rasters and the tool that
cut them. That value is written nowhere in the .atlas file. A reader holding
a finished bundle has every other part in hand and cannot invert SHA-256 for
the rest, so the sum is out of reach by construction, not by omission.
This is a property of format v3 as frozen, not a defect to fix: putting the derivation stamps into the manifest would restamp every bundle in every library.
The second ceiling: two derivers never stamp alike
A derivation stamp covers the deriving code's own source hash
(docs/ §4.2). That is deliberate and load-bearing: changing how a
level is reduced, or where the content bounds land, must invalidate every
pyramid, and a stamp that watched only the archive would quietly keep serving
the old derivation.
The consequence is exact and unavoidable: two derivers that write byte-identical tiles still stamp differently, because they are different tools. A library built end to end by two implementations carries the same tiles and the same canonical content under different twelve-hex names.
Both ceilings resolve the same way: a stamp is a rebuild-cost promise — "nothing that made this has moved" — and never a content promise. Reproducibility is proven where it is observable, at the tiles and at the composed bundle.
What is enforced instead
The proxies below run on every make test, and each of them would fail for
any change that could move a stamp:
- The stamp arithmetic itself.
format/holds the part-hash format, the order independence, the short form, the capture-day rule andbundle/ stamp_test.go VersionedFileNameto stated vectors. - Manifest byte-parity.
TestCorpusManifestsReEncodeExactly(format/): each committed corpus manifest parses intobundle/ corpus_test.go format/types and re-encodes to the committed bytes. The manifest's encoded bytes are a stamped part, so a schema that has moved by one byte is caught exactly where it would have changed the stamp.bundle - Identity derivation, end to end.
TestCorpusManifestsDeriveTheirIdentity: the file name, short stamp and capture day each corpus build actually carries are re-derived from its manifest alone. - Every recoverable payload.
TestCorpusLocationsRepackToTheRecordedPayloadpacks each world's unpacked locations back into the recorded payload bytes, both directions;TestCorpusInventoriesAgreeWithTheirHeadersholds the per-pyramid tile inventories to what the manifests promise. - The registry fold.
TestCorpusManifestsFoldAsALibrary: the ordering a stamp participates in — capture time, policy revision, stamp, locator — folds the corpus builds the way a library would.
What the committed corpus cannot carry is a whole .atlas archive — rasters
and all, they are hundreds of megabytes — so the checks that need a real file
in hand (part hashes against the wire, entry order, tiles stored uncompressed)
live in make corpus-smoke, the maintainer's non-gating walk of an installed
library (testing.md).
Where the measurements live
The corpus extractions under testdata/ record two real
builds — the proof city and the planet — file name, stamp, counts, payload
hashes and tile inventories, which is what the tests above measure against.
The pre-rewrite reproduction measurements, fixture by fixture, are archived
with the tree that took them on the golden-reference tag; the divergences
accepted from them are
decision 18.