You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
M6: identity, the gr: URI space, edges and export #14
Both id spaces are kept.
The legacy integer is what every link and every third party dataset for fifteen years uses.
The KCA id is what the current site actually keys on and what cache references resolve against.
Neither is derivable from the other, so a record with one of them can only be joined one way.
slug() is a contract.
Changing it renames every place and character node in every store anybody has built, so a change to it is a breaking change and is tested as one.
Cycles are normal. Book -> Work -> BestBook -> Book closes in three hops on almost every popular title.
Checklist
both id spaces kept, legacy and KCA, neither derived from the other
gr: URI space, built from the legacy id
slug() specified once and tested, with a note that changing it is a breaking change
the twelve edges, each carrying its surface and timestamp
contributed_by carries the role, in_series carries the position
traversal with --depth, defaulting to 1, asking for --yes above 500 nodes
JSONL export
RDF export, schema.org where it fits and grv: where it does not
The edge set is closed at the write. PutEdge refuses a predicate that is not one of the twelve, and the refusal names what to use instead. The alternative was catching it at the read, where a typo looks exactly like missing data: the query returns zero rows and nothing anywhere says why.
Four of the names M5 was writing were not the spec's, and fixing them changed two directions as well as two names. wrote ran author to book and is now contributed_by running book to author; contains ran list to book and is now listed_in running book to list. The direction reads worse in a sentence and that is fine, because Edges answers either way and one canonical direction is what stops the same fact landing twice under two names.
Places, characters and awards got tables of their own. They have no id on Goodreads and no page, so the slug is the id, and two places with the same name in different countries collide. That is a real limit and it is written down rather than papered over with a synthetic id that nothing else in the world shares.
The traversal gate is at 500 nodes and the count is taken with a walk that reads no records, so asking the question is cheap even when the answer is no.
Activity
tamnd commentedon Aug 15, 2026
Done in #25.
Three things worth writing down.
The edge set is closed at the write.
PutEdgerefuses a predicate that is not one of the twelve, and the refusal names what to use instead. The alternative was catching it at the read, where a typo looks exactly like missing data: the query returns zero rows and nothing anywhere says why.Four of the names M5 was writing were not the spec's, and fixing them changed two directions as well as two names.
wroteran author to book and is nowcontributed_byrunning book to author;containsran list to book and is nowlisted_inrunning book to list. The direction reads worse in a sentence and that is fine, becauseEdgesanswers either way and one canonical direction is what stops the same fact landing twice under two names.Places, characters and awards got tables of their own. They have no id on Goodreads and no page, so the slug is the id, and two places with the same name in different countries collide. That is a real limit and it is written down rather than papered over with a synthetic id that nothing else in the world shares.
The traversal gate is at 500 nodes and the count is taken with a walk that reads no records, so asking the question is cheap even when the answer is no.