Maya prints the hundred and thirty-five properties of a MusicRecording and reads them like a menu she is not hungry enough for.
Her old spreadsheet had three columns: song, artist, where I heard it. One of those columns was empty for six hundred rows. That spreadsheet was wrong in every way except the one that matters — it knew which fields Maya actually cared about.
She's right, and the graph agrees with her.
Drawing the ring#
A classification is the canonical shape of one kind of thing. Not the full schema.org property list — the ring drawn around it: the exact fields worth capturing when the thing is born.
- Required — the fields that make it itself. For a music recording: the name. That's it.
- Recommended — the disambiguators worth having:
byArtist,inAlbum, canonicalsameAsreferences. - Available — everything else. All 135 properties stay queryable underneath. The ring hides nothing; it just tells you where to start.
The registry ships 37 classifications across 7 categories — Person, Book, Event, Local Business, Podcast Episode, Ethereum Smart Contract — each one a decided answer to "which fields, in which shape." And decided is the load-bearing word. Because when two apps fill the same fields the same way, they produce the same bytes. And the same bytes produce the same ID.
Chapter two ended with the problem: the dictionary doesn't tell two people which blanks to fill. The classification is the answer. Convergence stops being a policy and becomes arithmetic.
Kerala, done properly#
import { buildAtomData } from "@0xintuition/classifications";
import { calculateAtomId } from "@0xintuition/ids";
const atomData = buildAtomData("music-recording", {
name: "Kerala",
byArtist: "Bonobo",
inAlbum: "Migration",
});
// {"@context":"https://schema.org/","@type":"MusicRecording",
// "name":"Kerala","byArtist":"Bonobo","inAlbum":"Migration"}
calculateAtomId(atomData);
// 0x6fa0de44d28a6d36067ea5e1db51d143d831c859357b35deab4b5c0f24305b08
Look at what the builder did. Typed input goes in; canonical JSON-LD comes out — keys in a fixed order, schema.org context attached, nothing improvised. The formatting decisions that would have made Maya's bytes different from the stranger's have all been made by the shape itself. Anyone, in any app, who builds Kerala from Migration by Bonobo — Maya, the jazz collector, a builder who hasn't heard of either of them — gets this exact string, and therefore this exact ID. No coordination. That's the entire trick.
While she's at it, Bonobo stops being a homemade string too:
buildAtomData("music-group", { name: "Bonobo" });
// {"@context":"https://schema.org/","@type":"MusicGroup","name":"Bonobo"}
// → 0x6eef2298f1fa180827e8b3becfe9b96c764370b0816161fc59105f613f2aef9c
An honest accounting#
Notice what just happened, because the graph never hides it: canonical Kerala (0x6fa0…5b08) is a different atom from chapter one's homemade "Kerala — Bonobo" (0xbdf3…9644). Building canonically prevents new divergence — it doesn't retroactively repair the old. There are now three Keralas in the world: Maya's string, the stranger's string out in the wild, and the real one.
That's not a failure; it's a to-do. The graph has a specific, elegant tool for saying "these are the same thing," and it gets its own chapter — right after the crate gets its second user, and the problem gets much, much bigger.
Where this is going#
The crate now has properly-shaped, convergent atoms. But atoms were never the collection. Maya doesn't love "Kerala"; she loves Kerala, by Bonobo, filed under downtempo, heard live at the Fillmore. Every italic in that sentence is a relationship — and in the graph, relationships are claims you can hold in your hand.
Next chapter, Maya makes her first one, using a verb she didn't invent.