Your LinkML Model Is Right. Your Pipeline Never Read It.
The ticket that lands on a Monday morning rarely says "semantic drift." It says: *rows rejected, unexpected value in `sex` column.* Someone traces it back. Six weeks earlier a curator added a permissible value to an enum in the team's LinkML model, complete with a `meaning` URI pointing at a specific ontology term. The model was correct that day and has been correct every day since. The warehouse constraint, the JSON Schema the API validates against, and the Avro subject in the registry were each written by hand from an older reading of that file, and none of them heard about the change.
Your LinkML Model Is Right. Your Pipeline Never Read It.
The ticket that lands on a Monday morning rarely says "semantic drift." It says: rows rejected, unexpected value in sex column. Someone traces it back. Six weeks earlier a curator added a permissible value to an enum in the team's LinkML model, complete with a meaning URI pointing at a specific ontology term. The model was correct that day and has been correct every day since. The warehouse constraint, the JSON Schema the API validates against, and the Avro subject in the registry were each written by hand from an older reading of that file, and none of them heard about the change.
That is the shape of the problem. Not a bad model. Not a bad engineer. A correct model that no downstream system can read, copied by people, drifting quietly from the moment the copy was made.
LinkML says more than most formats can hold
Teams reach for LinkML because it refuses to flatten what matters. A class declares is_a and actually inherits. A slot says whether it is required and whether it is multivalued, so cardinality is a statement rather than a convention. An enum is not a list of strings — each permissible value can carry a meaning, a compact URI over a declared prefix that binds "MALE" to a defined term in a published ontology instead of to a token that merely looks familiar. Classes and slots carry class_uri and slot_uri bindings of their own, and facets like pattern and minimum_value sit next to the slot they constrain.
In research data and anywhere two datasets have to be combined rather than merely stacked, that precision is the difference between "these columns have the same name" and "these columns mean the same thing."
Where the precision goes
None of it survives the border crossing, because the border crossing is a person.
Enums drift first. The model gains a permissible value; the CHECK constraint, the Avro symbol list, and the API's allowed-values array each need editing by a different team, and the slowest sets the system's actual behavior.
Ontology bindings never leave the file. The meaning URI was the expensive part — someone searched, compared candidates, decided. It appears in no table definition, no API contract, no catalog entry, so the next integrator maps that field by reading its name and guessing.
Inheritance gets resolved inconsistently. One engineer denormalizes the parent class's slots into every child table; another builds a join. Both are defensible; together they mean two teams describe the same model differently, and comparing their outputs is noise.
Optionality is transcribed from memory. required: true is one word in YAML and a schema-wide behavioral contract everywhere else. It gets dropped more often than anything, because dropping it never fails immediately.
Individually these are small. Together they change the file's status: the LinkML model stops being the source of truth and becomes documentation of intent.
The part that actually hurts: nobody records the losses
Some of these losses are unavoidable. Postgres has no notion of a meaning URI; Avro has no inheritance. A careful engineer translating LinkML into DDL has to leave things behind — that is not negligence, it is the target format being smaller than the source.
The failure is that the leaving-behind is never written down. No artifact anywhere in the pipeline says "the ontology binding on this column was not representable and was dropped." So when the systems disagree six months later, nobody can tell an intentional simplification from an accident, and every investigation becomes archaeology.
A translation you cannot audit is one you cannot trust — and one that has to be redone every time anyone asks a hard question.
What changes when the model has a governed home
CoreModels treats LinkML as a first-class schema format in both directions — format key linkml, YAML in and YAML out. Import a LinkML schema into a project and classes become governed types with is_a preserved as a real parent link; attributes and referenced slots become governed elements that keep their required and multivalued declarations; enums become managed taxonomies whose terms are the permissible values. Ranges resolve rather than degrade: a range naming another class becomes an actual reference to that type, and a range naming an enum becomes a reference to that taxonomy.
Most of all, the meaning travels. A class_uri, slot_uri, or meaning CURIE is expanded through the schema's own declared prefixes — and through a standard seed covering the vocabularies these models reach for, from schema.org and SKOS to the OBO family — and lifted into the governed graph's semantic-mapping layer. It stops being a comment inside a YAML file and becomes queryable metadata on a governed node that every other export reads.
From that one governed model the rest of the estate is an export away: JSON Schema for the services, SQL DDL for the warehouse in your vendor dialect, Avro for the registry, OWL for the semantics team, a Bitol ODCS contract for the catalog, and LinkML back out again for the curators who own the model. Import runs at Admin on a project; export runs at Viewer.
And an honest ledger of what didn't fit
Every transform call returns a lossiness list alongside its output, each entry naming a kind, a path, and a plain-language explanation. If a class declares mixins, the names are preserved for re-export but their slots are not merged in — recorded. If a class references top-level slots:, they are flattened into inline attributes — recorded. If a range names a type this schema does not define, it approximates as a string, keeps the original range text verbatim, and says so. Unknown LinkML keys are not errors at all; they ride along verbatim and are re-emitted where they were found.
success: true means the call ran, not that nothing changed. The ledger is the difference between a pipeline you can review and one you have to believe.
The original problem was never YAML versus DDL. It was that meaning had no shared home, so every projection was an act of faith performed by whoever picked up the ticket. Give the model one governed home, make every other format a projection of it, and require every projection to declare its losses — and the enum value added on a Monday reaches the warehouse the same week, with a receipt.
If you maintain a LinkML model and an estate that have quietly stopped agreeing, the transform quickstart in the CoreModels documentation shows the first import as a single call.