chore(metamodel): make regeneration reproducible, and pin down the dropped-typeof bug - #112
Merged
Merged
Conversation
…d-typeof bug The metamodel is generated by gen-rust from a linkml checkout, but nothing recorded which generator revision produced the committed crate. A regen from a different revision silently reverts whatever the crate has that the generator no longer emits -- as happened to the per-key map merge strategy, with no test failing. regen.sh now: * resolves the repo root from the script location and the sibling linkml checkout from the main working tree, so it works from a git worktree; * takes LINKML_DIR as an override; * stamps src/metamodel/GENERATED_FROM with the generator revision used and with every generator commit not yet in linkml/main -- while that list is non-empty the crate cannot be reproduced from upstream linkml alone; * grows a --check mode that regenerates into a temp dir, formats it the same way, and diffs against the committed crate without writing anything. --check reports drift today, and all of it is the output of two open linkml PRs (linkml/linkml#3919, linkml/linkml#3662). Tracked in #109. Also record the bug that motivated this, as failing tests rather than prose: LinkML spells the keys `typeof` and `abstract`, both Rust keywords, so the generated fields are `typeof_`/`abstract_` with nothing mapping between the two spellings -- serde drops the value without error and a derived type inherits nothing. type_ancestors truncates to the type itself, so rdf_datatype_iri and is_range_iri are not inherited and a type declared `typeof: uri` serializes as a literal instead of a named node. The fix is a generator change (linkml/linkml#3919) plus a regen, so the tests are #[ignore]d with a pointer to #108 rather than deleted; they are expected to pass unchanged once the regenerated metamodel lands. Un-ignore them in that commit. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This was referenced Aug 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
src/metamodel(linkml_meta) is generated bygen-rustfrom a linkml checkout, but nothingrecorded which generator revision produced the committed crate. That makes a regen
unreproducible and, worse, silently destructive: a regen from the wrong revision reverts whatever
the committed crate has that the generator no longer emits.
Not hypothetical — this was found while trying to regenerate. The per-key map merge strategy
(
option_map_overwrite, which keeps aslot_usageoverride ofannotationsfrom dropping theinherited ones, added in f79d7fe) was absent from the generator branch that was checked out; a
regen would have replaced it with whole-map
overwrite_except_noneand no test would have failed.What this changes
regen.sh:working tree, so it works from a git worktree instead of silently looking for
../linkmlnext tothe worktree;
LINKML_DIRas an override;src/metamodel/GENERATED_FROMwith the generator revision used and with everygenerator commit not yet in
linkml/main— while that list is non-empty, the crate cannot bereproduced from upstream linkml alone;
--check, which regenerates into a temp dir, formats it the same way, diffs against thecommitted crate, and writes nothing.
README.mddocuments both, plus the rule they enforce: a generator fix goes upstream as a linkml PRbefore the regenerated crate is committed here.
The bug this was gating, recorded as tests
LinkML spells the keys
typeofandabstract. Both are Rust keywords, so the generated fields aretypeof_/abstract_, and nothing maps between the two spellings — serde drops the value withouterror and a derived type inherits nothing:
determine_rdf_type_infois not at fault; its ancestor walk is correct and is being handed atruncated list. Consequences:
rdf_datatype_iriis not inherited,is_range_iriis not inherited(so a type declared
typeof: uriserializes as a literal instead of a named node),is_integer/is_floating_pointare false, andabstract:is dropped on four structs.The fix is a generator change (linkml/linkml#3919) plus a regen, neither of which belongs in this
PR. So the behaviour is committed as seven tests that fail today and are
#[ignore]d with a pointerto #108 — five in
schemaview/tests/typeof_inheritance.rsand two inruntime/tests/turtle_custom_types.rs. Confirmed failing for the right reason:Un-ignore them in the commit that lands the regenerated metamodel.
Current
--checkoutputDrift against the local generator stack, all of it the output of two open linkml PRs — the five
serde renames (#3919) and the
*OrSubtypebase-class variants (#3662). Everything else in the cratereproduces byte-for-byte after formatting,
Cargo.tomlincluded.Tracking, one issue per upstream PR so they close as they merge: #108 (#3919), #110 (#3662), #111
(#3661, no effect on this crate's output), with #109 for the regeneration itself.
Notes
--checkneeds a local linkml checkout, so it cannot run in CI as-is.src/metamodel/Cargo.toml~is a committed editor backup;--checkexcludes it rather thandeleting it here.
cargo fmt --all --checkandcargo test --workspace(72 suites) are clean.