Metamodel Version Row Mapper
Translate metamodel versions to and from the property maps the Neo4j graph store reads and writes.
Neo4j properties are scalars and flat arrays, while a version's content is lists, a map of label sets, and a map of property signature sets, so all four structural fields are serialized to JSON strings. JSON also handles names containing pipes, tabs, newlines and quotes, which these names routinely do: they come out of LLM extraction.
The save instant is informational, and is written twice. savedAt is the ISO-8601 string, which is what you want when you're looking at a node and wondering when it landed. savedAtEpochMillis is the same instant as a number, for filtering or grouping by time in an ad-hoc query; the string is no use for that, since Instant.toString() drops the fraction entirely at a whole second and 'Z' sorts above '.', making "…T00:00:00Z" compare greater than "…T00:00:00.500Z".
Neither field orders the history. The sequence property does that; see DrivineMetamodelVersionStore for why a clock can't express write order. Nothing here writes or reads sequence: Cypher assigns it off a per-schema counter, and it is storage bookkeeping, so it stays out of the strict round-trip below.
Reads are strict. A property this mapper wrote must be present when it is read again; a node missing one is corrupt, so the accessor throws and the store's surrounding guard skips the row with a warning. An empty string is corrupt too: an empty collection is written as [] or {}, so "" never comes from this mapper, and it fails the read like any other bad JSON.
Two things are optional, and absent means "no former names were declared": the version-level entityTypeAliases property, and the aliases field inside a stored property signature. Writing them only when they hold something means an alias-free stamp stores exactly the properties this mapper stored before either existed, and a node written by that older build reads back here as a stamp declaring neither. Aliases feed the content hash, so a stamp carrying them and failing to store them would fail its own integrity check on the way back in and be unreadable for good.